官术网_书友最值得收藏!

Templates

Flask has built-in support for Jinja2 templating. Jinja2 templating has a standard defined pattern for rendering the HTML. We can place dynamic content by passing the context argument. Jinja2 gives an ability to render HTML with some expressions and conditions, extending and including template features.

Flask follows a standard templating scaffolding structure to lay out all template files. The following is the scaffolding we followed by creating a templates directory under the project's root directory and then creating subdirectories based on other module names:

Here, we have created templates as per the module and put the generic templates under the root directory.

Similarly, we have maintained the static file's scaffolding:

We kept the static libraries and modules-related files. With the help of the url_for method, we can get the relative path of any static files and routes. Hence, in the following template, we included all static files using a url_for method, such as <link rel="stylesheet" href="{{ url_for('static', filename='bootstrap/css/bootstrap.min.css')}}">.

In the same way, we are going to include all static files in the base template.

File—templates/base.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta name="author" content="AbdulWahid AbdulHaque">
<title>Flask Todo App</title>

<link rel="stylesheet" href="{{ url_for('static', filename='bootstrap/css/bootstrap.min.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='bootstrap/css/bootstrap.min.css.map') }}">
{% block css %}{% endblock %}

<script type="text/javascript" src="{{ url_for('static', filename='jquery/jquery-3.3.1.min.js')}}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='bootstrap/js/bootstrap.min.js')}}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='popper/popper.min.js')}}"></script>
{% block js %}{% endblock %}
</head>
<body>
{% include 'navbar.html' %}
{% block body %}{% endblock %}
<script type="text/javascript">
$('.dropdown-toggle').dropdown();
</script>
</body>
</html>

We defined all generic HTML that is required on all other templates. We also created a basic bootstrap navbar and kept this in navbar.html, which is included in the base.html template by {% include 'navbar.html' %}. As you can see, Jinja2 templating makes it super easy to maintain the templates and provide a standard pattern.

The following is a code snippet of the navbar.html template where we created a navbar using Bootstrap CSS classes.

File—templates/navbar.html:

<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#">Todo's</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
{% if current_user.is_authenticated %}
<ul class="navbar-nav ml-auto">
<li class="nav-item dropdown ml-auto">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Welcome <i>{{ current_user.email }}</i>
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="../auth/logout">Logout</a>
</div>
</li>
</ul>
{% endif %}
</div>
</nav>

While designing navbar.html, we added some conditional statements to display the logged-in user's information and logout options when the user is logged in.

Let's move on to the sign up and login page. The following is the code snippet for the sign up page.

File—templates/auth/signup.html:

{% extends "base.html" %}

{% block body %}
<div class="container align-middle mx-auto" style="width:30%; margin-top:5%">
<div class="card bg-light mb-3">
<div class="card-header"><h3>Sign Up</h3></div>
<div class="card-body">
<form method="post">
{{ form.hidden_tag() }}
{% if form.errors %}
{% for error in form.errors.values() %}
<div class="alert alert-danger" role="alert">
{{error}}
</div>
{% endfor %}
{% endif %}
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
{{ form.email(class_="form-control", id="exampleInputEmail1", placeholder="Email", maxlength=128)}}
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
{{ form.password(class_="form-control", placeholder="Password") }}
</div>
<div class="form-group">
<label for="exampleInputPassword">Confirm Password</label>
{{ form.confirm_password(class_="form-control", placeholder="Confirm Password") }}
</div>
<div class="form-group">
{{ form.submit(class_="btn btn-primary btn-lg") }}
<a class="float-right" href="login">Already have account.</a>
</div>
</form>
</div>
</div>
</div>
{% endblock %}

Here is the output of the Sign Up page:

On the HTTP GET request on the auth.signup view, this will return an empty form and render it through the signup.html template. We also added code to receive the sign up data on the HTTP POST request in the sign up view. We persist the user data on the sign up process using the User model.

Here is the login template.

File—templates/auth/login.html:

{% extends "base.html" %}

{% block body %}
<div class="container align-middle mx-auto" style="width:30%; margin-top:5%">
<div class="card bg-light mb-3">
<div class="card-header"><h3>Login</h3></div>
<div class="card-body">
<form method="post">
{{ form.hidden_tag() }}
{% if form.errors %}
<div class="has-error"><strong>Unable to login. Typo?</strong></div>
{% endif %}
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
{{ form.email(class_="form-control", id="exampleInputEmail1", placeholder="Email", maxlength=128)}}
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
{{ form.password(class_="form-control", id="exampleInputPassword1", placeholder="Password") }}
</div>
<div class="form-group">
{{ form.submit(class_="btn btn-primary btn-lg") }}
<a class="float-right" href="signup">New around here? Sign up</a>
</div>
</form>
</div>
</div>
</div>
{% endblock %}

Now, the user can proceed and log in to the system, For login, we have created the login form and rendered it through the auth.login view. The following is a screenshot of the Login page:

On the HTTP POST request, we are processing the user login mechanism using the Flask-Login extension, which provides a function called login_user and performs the login process. It creates a session and adds user_id into the session to remember the user for the further request until we remove the user from the session or perform the logout with the logout_user method, as mentioned in the auth.logout view.

The authentication process completes here, as the user login executes successfully and redirects the user to another page or template. Now, it's time to move on to the todo module.

主站蜘蛛池模板: 慈溪市| 明星| 农安县| 盐亭县| 南投市| 砀山县| 库尔勒市| 夏津县| 贵南县| 塔河县| 萍乡市| 辉县市| 阜平县| 上犹县| 东安县| 湘乡市| 开原市| 遂溪县| 东丰县| 曲靖市| 原阳县| 梧州市| 达尔| 遂川县| 岚皋县| 莲花县| 平遥县| 绥阳县| 乳源| 和林格尔县| 洛南县| 澄城县| 泾源县| 清苑县| 寿阳县| 乌兰察布市| 修水县| 剑河县| 格尔木市| 海宁市| 靖江市|