7.静态文件、模版、消息闪现与Jinja2

一. 静态文件访问原理

举例:

新建文件夹 app/static, 并在该文件夹下放入图片文件。
运行flask, 访问http://localhost:5000/static/图片名。 
发现可以访问文件

flask是如何做到访问静态文件的呢? 我查看app/init.py的create_app中 app=Flask(name),Flask的源码:

def __init__(
        self,
        import_name,
        static_url_path=None,
        static_folder='static',    # 默认的static文件的 路径
        static_host=None,
        host_matching=False,
        subdomain_matching=False,
        template_folder='templates',   # 默认的template文件的路径
        instance_path=None, 
        instance_relative_config=False,
        root_path=None
    ):

以及通过注册视图函数的方式实现通过url访问static文件夹的:

        if self.has_static_folder:
            assert bool(static_host) == host_matching, 'Invalid static_host/host_matching combination'
            self.add_url_rule(   # 注册视图函数
                self.static_url_path + '/<path:filename>',
                endpoint='static',
                host=static_host,
                view_func=self.send_static_file
            )


二. 模版文件的位置和修改方案

templates文件夹和static文件夹一样, 都是有默认设置的。我们放入app/templates文件下的html文件,都可以在视图函数中,通过render_template('html文件名') 来访问并返回给网站页面。

修改默认默认templates文件夹或static文件夹的位置, 我们可以对app = Flask(__name__)添加参数来实现: 比如:

app = Flask(__name__, static_folder='static2', template_folder='tempaltes2')
# 这样static默认文件夹就在  app/static
# 这样templates默认文件夹就在  app/templates

我们可以对蓝图修改默认的static或templates文件夹位置

app/web/blueprint.py中这样修改

web = Blueprint('web', __name__, static_folder='static', template_folder='templates')

# 这样static文件夹在 app/web/static, static文件不建议这样, 因为static文件很可能不同的蓝图都会使用
# 这样templates文件夹在 app/web/templates


三. 使用Jinja2

1. 在Jinja2中读取字典和对象

Jinja2模糊了对象和dict, 在jinja2中访问他们方法是一样的 假设有视图函数:

@web.route('/test')
def test():
    r = {
        'name': 'cannon',
        'age': 25
    }
    return render_template('test.html', data=r)    

对应的test.html代码中:

<!DOCTYPE html>
<html lang='en'>
<head>
    <meta charset='UTF-8'>
    <title></title>
</head>
<body>
    {{ data.age }}
    {{ data['age'] }}
</body>
</html>

2. 流程控制语句

if语句

test.html:

<body>
    {{ data.age }}
    {{ data['age'] }}
    {% if data.age < 18 %}
        {{ data.name }}
    {% elif data.age == 18 %}
        do something
    {% else %}
        {{ data.age }}
    {% endif %}
</body>

for in循环

test.html:

<body>
    {% for key, value in data.items() %}
        {{ key }}
        {{ value }}
    {% endfor %}
</body>

3. 使用模版继承

layout.html:

<!DOCTYPE html>
<html lang='en'>
<head>
    <meta charset='UTF-8'>
    <title></title>
</head>
<body>
    {% block head %}
        <div> This is head </div>
    {% endblock %}
    {% block content %}
        This is content
    {% endblock %}
    {% block foot %}
        <div> This is foot </div>
    {% endblock %}
</body>
</html>

在别的html页面继承layout.html
test.html:

{% extends 'layout.html' %}
{% block content %}
    {{ super() }}
    {{ data.age }}
    {{ data['age'] }}
    {% if data.age < 18 %}
        {{ data.name }}
    {% elif data.age == 18 %}
        do something
    {% else %}
        {{ data.age }}
    {% endif %}
{% endblock %}

4. 过滤器与管道命令

过滤器

1. default

test.html:

{% extends 'layout.html' %}
{% block content %}
    {{ super() }}
    {{ data.age }}
    {{ data['age'] }}
    {% if data.age < 18 %}
        {{ data.name }}
    {% elif data.age == 18 %}
        {{ data.school | default('不存在') }}   {# 访问不存在的变量,default才会生效 #}
    {% else %}
        {{ data.age }}
    {% endif %}
{% endblock %}
如果想data.school=None时,default也生效, 使用default('不存在', true) (加上一个true参数)
2. length

test.html:

{% extends 'layout.html' %}
{% block content %}
    {{ super() }}
    {{ data.age }}
    {{ data['age'] }}
    {% if data.age < 18 %}
        {{ data.name }}
    {% elif data.age == 18 %}
        {{ data | length() }}  {# 得到data的长度 #}
    {% else %}
        {{ data.age }}
    {% endif %}
{% endblock %}
3. 更多的过滤使用方法,可以去官方文档查看

四. urlfor 反向构建URL

以前注册视图函数的时候, 有个endpoint参数,我们并没有说它的作用。endpoint其实是用来反向获取url的。

新建app/static/test.css, 现在我想让app/templates/layout.html去加载test.css:

<!DOCTYPE html>
<html lang='en'>
<head>
    <meta charset='UTF-8'>
    <title></title>
    <link rel="stylesheet" href="{{ url_for('static', filename='test.css') }}">  
    {# url_for的使用方法 第一个参数是endpoint #}
    {#    <link rel="stylesheet" href="/static/test.css">#}
</head>
<body>
{% block head %}
    <div> This is head</div>
{% endblock %}
{% block content %}
    This is content
{% endblock %}
{% block foot %}
    <div> This is foot</div>
{% endblock %}
</body>
</html>

flask中能用url_for的, 尽量都用url_for


五. 消息闪现、SecretKey与变量作用域with

1.消息闪现 Messageing Flash

我们在app/web/book.py修改test视图函数:

from flask import flash

@web.route('/test')
def test():
    r = {
        'name': None,
        'age': 18
    }

    flash('hello, cannon')   # 使用flash
    return render_template('test.html', data=r)

对app/templats/test.html做修改:

{% extends 'layout.html' %}
{% block content %}
    {{ super() }}
    {% if data.age < 18 %}
        {{ data.name }}
    {% elif data.age == 18 %}
        {{ data | length() }} 
        {% set messages = get_flashed_messages() %}    {# 对应的使用get_flashed_messages #}
        {{ messages }}  
    {% else %}
        {{ data.age }}
    {% endif %}
{% endblock %}

我们运行flask并访问localhost:5000/test,报错了: 


消息闪现使用到了 session, 我们需要在配置文件secure.py添加secretkey:

DEBUG = True
SQLALCHEMY_DATABASE_URI = 'mysql+cymysql://root:@localhost:3306/fisher'
SECRET_KEY = 'wjdiajsjkskcnndijqwiodjieijqijwiwqijfbryguhtrvwpqwqdnxjj'

运行后得到结果:

This is head
This is content
['hello, cannon']    # flash得到的数据
This is foot

2.category参数的使用

修改app/web/book.py的test视图函数, 加入category参数:

from flask import flash

@web.route('/test')
def test():
    r = {
        'name': None,
        'age': 18
    }

    flash('hello, cannon', category='error')   # 使用flash
    flash('hello, cannon2', category='worning')   # 使用flash
    
    return render_template('test.html', data=r)

修改app/templats/test.html:

{% extends 'layout.html' %}
{% block content %}
    {{ super() }}
    {% if data.age < 18 %}
        {{ data.name }}
    {% elif data.age == 18 %}
        {{ data | length() }} 
        {% set messages = get_flashed_messages(category_filter=['error']) %}
        {# category参数对应使用category_filter #}
        {{ messages }}  
    {% else %}
        {{ data.age }}
    {% endif %}
{% endblock %}

这样 只会显示 category为error的flash传递的数据

3.with缩小变量作用域

在Jinja2中使用with语句, 则变量作用域只在with 和endwith之间: 
修改app/templats/test.html:

{% extends 'layout.html' %}
{% block content %}
    {{ super() }}
    {% if data.age < 18 %}
        {{ data.name }}
    {% elif data.age == 18 %}
        {{ data | length() }} 
        {% with messages = get_flashed_messages(category_filter=['error']) %}
        {{ messages }}     {# messages可以显示 #}
        {% endwith %}
        {{ mesages }}      {# messages不能显示 #}
    {% else %}
        {{ data.age }}
    {% endif %}
{% endblock %}

猜你喜欢

转载自blog.csdn.net/weixin_41207499/article/details/80739634