继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Flask 入门之旅(三)

周萝卜
关注TA
已关注
手记 53
粉丝 27
获赞 85

在通常的 Web 程序中,访问一个 URL 地址,一般都会返回一个 HTML 页面,而我们的数据就是嵌套在这些 HTML 代码当中的,再辅以 JavaScript 和 CSS 等,就组成了一个完整的前端页面了。

当然,对于 Flask 来说,它所包含的 HTML 页面还会包含一些变量和逻辑运算等代码,这些组合到一起就是模板。执行这些变量替换和逻辑计算工作的过程被称为渲染,这个工作由 Flask 自带的模板渲染引擎——Jinja2 来完成。

按照默认的设置,Flask 会从程序实例所在模块同级目录的 templates 文件夹中寻找模板,所以我们可以在 app.py 文件的同级目录下创建一个 templates 文件夹,用来存储模板文件。

下面我们先来简单熟悉下 Flask 模板的用法

模板基本语法

我们先来看一段例子,下面是 HTML 代码中嵌套了 Jinja2 的控制语法

<h1>{{ username }}的 Web 网站</h1>
{% if auth %}
<p>{{ admin }}</p>
{% else %}
<p>陌生人</p>
{% endif %} {# 大部分 Jinja 语句都需要声明关闭 #}

模板基本的三种定界符
{{ … }} 用来标记变量。比如在上例中就可以渲染出 username 所对应的具体数据

{% … %} 用来标记语句,比如 if 语句,for 语句等。例子中的 if…else… 语句就是简单的判断

{# … #} 用来写注释。

在 Jinja2 中允许我们使用大部分 Python 对象,比如字符串、列 表、字典、元组、整型、浮点型、布尔值。它支持基本的运算符号 (+、-、*、/等)、比较符号(比如==、!=等)、逻辑符号(and、 or、not和括号)以及in、is、None和布尔值(True、False)。

渲染模板

我们一般使用 Flask 提供的渲染函数 render_template() 来渲染模板

from flask import render_template 
@app.route('/test') 
def test():    
    name = 'admin'
    return render_template('test.html', user=name)

render_template 函数第一个参数文模板文件名,一般会在 templates 目录下寻找。还可以以关键字参数的形式传入变量到模板,这样在模板中就可以使用 user 这个变量了,其变量值为 ‘admin’。
下面我们就把上一节中在视图函数中书写的 HTML 代码整理到对应的模板中

整理模板

对于 needLogin1 页面,我们原来的视图函数是

@app.route('/needlogin1/')
def needLogin1():
    if 'loginID' in session:
        return '<h1>Hello, needLogin1!</h1>'
    else:
        return """
            <h1>Login</h1><a href="%s">Go To Login</a>
                """ % url_for('login', next=request.url)

我们可以分别在 templates 创建两个文件,hello.html 和 needlogin.html
对于 hello.html 文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Web</title>
</head>
<body>
<h1>Hello, {{ user }}!</h1>
</body>
</html>

对于 needlogin.html 文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Web</title>
</head>
<body>
<h1>Login</h1><a href="{{ url_for('login', next=request.url) }}">Go To Login</a>
</body>
</html>

接着我们再改写视图函数 needLogin1

@app.route('/needlogin1/')
def needLogin1():
    if 'loginID' in session:
        user = 'needLogin1'
        return render_template('hello.html', user=user)
    else:
        return render_template('needlogin.html')
        

这部分代码可以检出代码3a来查看

链接

在上面 needlogin.html 文件中你应该发现了,对于 href 属性,我们使用了 url_for() 这个函数来获取 URL 链接,这是和前面讲解的视图函数中 url_for 非常相似的。

url_for() 函数最简单的用法是以视图函数名作为参数,返回对应的 URL。当然还是像例子中展示的那样,传递额外的参数到查询字符串中 url_for(‘login’, next=request.url)。

变量与结构控制

在前面我们简单实践了 Flask 模板的变量与结构控制的用法,下面我们来详细说明下它们的功能

变量

在上面的例子中,我们使用了 {{ user }} 表示一个变量,它是一种特殊的占位符,告诉模板引擎这个位置的值需要从渲染模板时使用的数据中获取。

Jinja2 可以识别很多复杂的变量类型,比如列表、字典,对象等。

<p>这是字典: {{ mydict['key'] }}.</p> 
<p>这是列表: {{ mylist[3] }}.</p> 
<p>可变索引的列表: {{ mylist[myindex] }}.</p> 
<p>调用方法: {{ myobj.somemethod() }}.</p>

还可以使用一些过滤器,来修改变量,从而达到快速处理数据的效果。过滤器名添加在变量名之后,中间使用竖线分隔。

{{ name|title }} # 把变量name标题化

一些常用的过滤器

过滤器 说明
safe 渲染值时不转义
capitalize 首字母大写,其余字母小写
lower 转换成小写
upper 转换成大写
trim 去掉首尾空格
escape 转义 HTML 文本
default 设置默认值

这里我们着重说一下 safe 过滤器,默认情况下,Jinja2 会转义所有 HTML 标签,比如如果传入”

你好

“,会被渲染成”<hi>你好</h1>“,此时浏览器就会把

标签当作时一个普通字符来展示。而当我们需要把变量按照 HTML 代码来展示时,就可以使用 safe 过滤器

{{ "<h1>你好</h1>"|safe }}

控制结构

我们常用的控制结构有两种,即 for 循环和 if 判断。下面是这两种控制结构的例子

# if 判断
{% if user %}     
Hello, {{ user }}! 
{% else %}     
Hello, Stranger! 
{% endif %}
# for 循环
{% for user in users %}         
<li>{{ user }}</li>     
{% endfor %} 

模板继承

模板的继承类似于 Python 中的继承,即我们可以把页面上的一些通用原始编写到基模板中,然后其他子模版只需要编写对应页面特殊的代码即可,其他比如导航栏,页脚等内容可以放到基模板中编写。

先来编写基模板,base.html

<html> 
<head>     
{% block head %}     
<title>{% block title %}{% endblock %} - My Web</title>     
{% endblock %} 
</head> 
<body>     
{% block body %}     
{% endblock %} 
</body> 
</html>

在基模板中,我们用 block 来标记需要替换的部分,在上面的例子中我们定义了 head、title 和 body 块,那么子模版就可以任意修改这三块内容了
编写子模板,我们创建一个 user.html 模板

{% extends "base.html" %} 
{% block title %}User{% endblock %} 
{% block head %}     
{{ super() }}     
<style>     
</style> 
{% endblock %} 
{% block body %} 
<h1>Hello, World!</h1> 
{% endblock %}

使用 extends 来引入基模板,之后再重新定义3个 block 块。这里需要注意 super 的使用,如果在子模板中没有 super,那么子模板会覆盖基模板中的内容,如果添加了 super,就是追加内容,即对应的 block 块中会包含基模板的内容。

集成 Bootstrap

Bootstrap 是 Twitter 开发一个开源框架,他有许多可用的界面组件,可以帮助我们快速的打架前端页面。当然要集成 Bootstrap 框架,我们就需要对模板进行相关的改动,而这些完全可用交给插件 Flask-Bootstrap 来完成。

pip install flask-bootstrap # 安装插件

在 Flask app 中初始化 Flask-Bootstrap

from flask_bootstrap import Bootstrap
...
bootstrap = Bootstrap(app)

初始化 Flask-Bootstrap 之后,就可以在程序中使用一个包含所有 Bootstrap 文件的基模板。 这个模板利用 Jinja2 的模板继承机制,让程序扩展一个具有基本页面结构的基模板。

完善程序

下面我们就把前面写的模板通过 bootstrap 来优化下,首先是基模板,包含通用的导航栏

{% extends "bootstrap/base.html" %} 
 
{% block title %}My Web{% endblock %}{% block navbar %}
<div class="navbar navbar-default navbar-static-top" role="navigation">
        <div class="container">
            <div class="navbar-header">
                <button class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon icon-bar"></span> <span class="icon icon-bar"></span> <span class="icon icon-bar"></span> </button>
                <a href="#" class="navbar-brand">HelloFlask</a>
            </div>
            <div class="collapse navbar-collapse">
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="#home" class="smoothScroll">首页</a></li>
                    <li><a href="#intro" class="smoothScroll">网站简介</a></li>
                    <li><a href="#team" class="smoothScroll">风格</a></li>
                    <li><a href="#portfolio" class="smoothScroll">作品</a></li>
                    <li><a href="#contact" class="smoothScroll">联系我们</a></li>
                </ul>
            </div>
        </div>
    </div>
{% endblock %}{% block content %}
<div class="container">
    {% block page_content %}{% endblock %}
</div> {% endblock %}

接下来我们在 hello.html 模板上继承该基模板,并查看效果

{% extends "base.html" %}
{% block title %}My Web - Index{% endblock %}{% block page_content %}
<div class="page-header">
    <h1>Hello, {{ user }}!</h1>
</div> 
{% endblock %}

刷新页面,可以看到现在的页面如下
图片描述

添加 Favicon

Favicon 是网站的特殊标记,可以展示在收藏夹、浏览器标签中的图标。现在我们就为我们的网站添加一个 Favicon。

首先我们在 templates 文件夹的同级目录上创建一个 static 文件夹,然后在使用一些在线工具制作 favicon.ico 文件,并放置到该目录下

在线转换工具有很多,可以使用这个

最后我们在 HTML 页面中声明 Favicon 的路径,在 base.html 模板中的 标签中添加一个

<head>
{% block head%}
    {{ super() }}
    <meta charset="utf-8">
    <title>
    {% block title %}My Web{% endblock %}
    </title>
    <link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='favicon.ico')}}">
{% endblock %}
</head>

消息闪现

Flask 还提供了一个非常有用的函数 flash(),它可以在页面上闪现需要展示给用户的消息。它的工作原理就是把相关的信息存储在浏览器的 session 中,然后我们在模板中使用全局函数 get_flashed_messages() 获取消息并将其显示出来。

下面我们对登陆成功的用户闪现消息,先在登陆视图函数中添加 flash

@app.route('/login/')
def login():
    session['loginID'] = 'admin'
    target = request.args.get('next')
    flash(u"你登陆成功了!")
    if check_next(target):
        return redirect(target)
    return redirect(url_for('hello'))

然后再在 hello.html 模板中渲染 flash 消息

{% extends "base.html" %}{% block title %}My Web - Index{% endblock %}{% block page_content %}{% for message in get_flashed_messages() %}
 <div class="alert alert-warning">
     <button type="button" class="close" data-dismiss="alert">&times;</button>
     {{ message }}
 </div>
{% endfor %}
<div class="page-header">
    <h1>Hello, {{ user }}!</h1>
</div>
{% endblock %}

最终的效果
图片描述

这部分的代码,可以检出代码库中的 3b

总结

本节我们学习了 Flask 中模板的使用,这对于我们快速完成 Web 应用开发是非常方便的。

图片描述

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP