狼书第三章Jinja2模板总结

时间:2021-04-29 05:36:26

不得不说这一张给了我很大的帮助和启发,所以这一篇的总结我会好好的写,不单单是书上的内容,更多是我的个人思路和理解

首先给出全部的app.py的代码顺着代码代入思路和知识点

import os
from flask import Flask, render_template, flash, redirect, url_for, Markup

app = Flask(__name__)
app.secret_key = os.getenv('SECRET_KEY', 'secret string')
app.jinja_env.trim_blocks = True
app.jinja_env.lstrip_blocks = True

user = {
    'username': 'Grey Li',
    'bio': 'A boy who loves movies and music.',
}

movies = [
    {'name': 'My Neighbor Totoro', 'year': '1988'},
    {'name': 'Three Colours trilogy', 'year': '1993'},
    {'name': 'Forrest Gump', 'year': '1994'},
    {'name': 'Perfect Blue', 'year': '1997'},
    {'name': 'The Matrix', 'year': '1999'},
    {'name': 'Memento', 'year': '2000'},
    {'name': 'The Bucket list', 'year': '2007'},
    {'name': 'Black Swan', 'year': '2010'},
    {'name': 'Gone Girl', 'year': '2014'},
    {'name': 'CoCo', 'year': '2017'},
]


@app.route('/watchlist')
def watchlist():
    return render_template('watchlist.html', user=user, movies=movies)


@app.route('/')
def index():
    return render_template('index.html')


# register template context handler
#自定义上下文变量,返回值必须为字典
@app.context_processor
def inject_info():
    foo = 'I am foo.'
    return dict(foo=foo)  # equal to: return {'foo': foo}


# register template global function
#自定义全局函数
@app.template_global()
def bar():
    return 'I am bar.'


# register template filter
@app.template_filter()
def musical(s):
    return s + Markup(' ♫')


# register template test
@app.template_test()
def baz(n):
    if n == 'baz':
        return True
    return False


@app.route('/watchlist2')
def watchlist_with_static():
    return render_template('watchlist_with_static.html', user=user, movies=movies)


# message flashing
@app.route('/flash')
def just_flash():
    flash('I am flash, who is looking for me?')
    return redirect(url_for('index'))


# 404 error handler
@app.errorhandler(404)
def page_not_found(e):
    return render_template('errors/404.html'), 404


# 500 error handler
@app.errorhandler(500)
def internal_server_error(e):
    return render_template('errors/500.html'), 500

app.run(debug=True)

 首先创建一个实例

将用户列表和电影的信息全部传到一个新的url中,在新的url中去返回一个html页面,来输出这些信息

所以这里就新建了一个watchlist.html,这个html的目的就是为了返回url对应视图函数传入的内容

watchlist.html的代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{user.username}}'s Watchlist</title>
</head>
<body>

<a href="{{ url_for('index') }}">← Return</a>
<h2>{{user.username}}</h2>

{% if user.bio %}
    <i>{{user.boio}}</i>
{% else %}
    <i>This user has not provided a bio.</i>
{% endif %}

<h5>{{ user.username }}'s Watchlist ({{movies | length}}):</h5>
<ul>
    {% for movie in movies %}
        <li>{{movie.name}} - {{movie.year}}</li>
    {% endfor%}
</ul>

</body>
</html>

主要有俩个知识点,也就Jinja2模板中常用的语法,for循环和if判断

唯一值得注意的就是要对应开始就要对应结束

{% if xxx %} -----{% endif %}

{% for xxx %} ----{% endfor %}

模板中的变量,需要视图函数导入

然后在根据代码流程分析:

1.上下文变量:

上下文变量是在模块中可以直接使用的,相当于模块中的全局变量。

自定义上下文变量是利用装饰器@app.context_processor

(1)@app.context_processor

def xxx():

  pass

(2)当然还有先定义函数,然后将函数以方法的方式去返回

def xxx():

  pass

app.context_processor(xxx)

狼书第三章Jinja2模板总结

2.全局函数:全局函数就相当于是所有模块都可以使用的.

自定义全局函数是利用装饰器:@app.template_global:

狼书第三章Jinja2模板总结

3.过滤器:模板中的工具,操作对象|过滤方法(例如在watchlist.html{{movies|length}})计算这个movies有多长

狼书第三章Jinja2模板总结

4.测试器:测试器从字面理解就是用来判断和对比测试

关键装饰器@app.templat_text(),像下面这个例子的意思就是给baz函数传入参数,进行对比,再根据对比来返回结果

狼书第三章Jinja2模板总结

5.基模板:来到Jinja2的灵魂之处了

基模板的意思,通俗去理解就是共享块

而块的概念就是将一个模板分成若干个块

<!DOCTYPE html>
<html>
<head>
    {% block head %}
        <meta charset="utf-8">
        <title>{% block title %}Template - HelloFlask{% endblock %}</title>
        <link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='favicon.ico') }}">
        {% block styles %}
            <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css' ) }}">
        {% endblock %}
    {% endblock %}
</head>
<body>
<nav>
    <ul><li><a href="{{ url_for('index') }}">Home</a></li></ul>
</nav>

<main>
    {% for message in get_flashed_messages() %}
        <div class="alert">{{ message }}</div>
    {% endfor %}
    {% block content %}{% endblock %}
</main>
<footer>
    {% block footer %}
        <small> © 2018 <a href="http://greyli.com" title="Written by Grey Li">Grey Li</a> /
            <a href="https://github.com/greyli/helloflask" title="Fork me on GitHub">GitHub</a> /
            <a href="http://helloflask.com" title="A HelloFlask project">HelloFlask</a>
        </small>
    {% endblock %}
</footer>
{% block scripts %}{% endblock %}
</body>
</html>

 从上述代码分析

{%block head%} 中有俩个块

一个是{%block title%}放置标题,

另外一个是{%block style%}用来存放读取css链接的块,每个块结束,都要对应的使用{%endblcok%}这个关键字来结束块。

在<body>这个标签中首先有一个Home跳转小按钮,跳转到主页,

紧接着在<main>的标签中读取消息闪现中的消息,并存放了{%block content%}的信息,方便子模块继承

在<footer>标签中创建{%block footer%}这个块,用来存放页脚信息。

最后一个块就是{%block script%}用来放置js脚本链接的块

6.子模版的继承问题

子模版的只要是继承了基模块,那么在模板就开始要使用extend '基模板名',

并且在写入内容或者修改内容的时候,必须是在主模块的已经定义了块中进行操作,

如{%block content%} xxx {%endblock%},中间的内容就是子模块新增的。

7.加载静态文件(js.css.img)

使用<link>标签来加载静态文件,在{%block style%}中加载css文件,在{%block scripts%}中加载js文件,如下所示

狼书第三章Jinja2模板总结

8.宏

9.宏加载静态文件

10.加载Favion:网页有一个小图标

狼书第三章Jinja2模板总结

在模块中直接使用link标签,留意标签属性和文件选择