Flask Day3

Author: 陈伦巨

Data: 2019-04-06

Email: 545560793@qq.com

github: https://github.com/smartisantt

一、装饰器

装饰器条件
1.外层函数嵌套内层函数
2.外层函数返回内层函数
3.内层函数调用外层函数的参数

在这里我们用装饰用来给用户做验证,例如下面是大体的装饰器框架:

def is_login(func):

    def check():
        return func() # 2.后执行

    return check # 1.先执行

在需要验证的地方使用@ is_login来装饰,装饰器先执行,然后再执行被装饰的函数。

我们在工程同级目录下新建一个utils包,在里面新建一个functions.py文件

from functools import wraps

from flask import session,render_template

# 创建验证用户登陆功能装饰器
def is_login(func):
    @wraps(func)
    def check():
        try:
            session['login_status']
            # 登录过后,再执行被装饰的函数。访问index.html 页面
            return func()
        except:
            # 没有登录不让访问,跳转到session_login.html页面
            return render_template('session_login.html')
    return check
  • 装饰器的作用: 在不改变原有功能代码的基础上,添加额外的功能,如用户验证等
  • @wraps(view_func)的作用: 不改变使用装饰器原有函数的结构(如__name__, __doc__)
  • 不使用wraps可能出现的ERROR: view_func...endpoint...map...

二、蓝图

MVC

M:模型(Model) 定义一个类关联数据表

V:视图(View) templates

C: 控制器(controller) 业务逻辑

我们安装MVC把原来的文件拆分。

在同级目录下新建app包,在里面新建app.py文件,之前更路由相关功能的函数全都剪切到这个文件里面,然后完成相应导包工作,然后运行程序,发现输入原来正确的地址并无法访问网页。

这个要使用第三方库管理路由。安装第三方库 pip install flask-blueprint

使用范例:

from flask import Blueprint # 安装完之后在views.py文件中导包

# 蓝图,管理路由地址
# 第一步,在views.py设置蓝图
blue = Blueprint('first', __name__)

# 第二步:在工程文件下注册蓝图
app.register_blueprint(blueprint=blue)

redirect 是跳转到指定页面,浏览器地址是你跳转的地址

url_for是反向解析,通过蓝图的第一个参数.跳转函数名的语法格式实现跳转。

# 页面跳转
redirect('/login/')

# url_for('蓝图的第一个参数.跳转的函数名') 反向解析路由地址
redirect(url_for('first.login'))

建议使用第二种,路由地址变化时但无需更改代码。

我们现在回头再看看之前写的模拟登陆注册的代码:

注册模块:

# app.route 更改为blue来管理路由
@blue.route('/register/', methods=['GET', 'POST'])
def register():
    print(request.method)
    if request.method == 'GET':
        return render_template('register.html')
    if request.method == 'POST':
        username= request.form.get('username')
        password= request.form.get('password')
        password2= request.form.get('password2')
        if username == 'ququ' and password == password2 == '123456':
            # 下面的代码只是重新渲染当前页面,浏览器地址还是register
            # return render_template('login.html')
            # 下面的代码,实现页面重新选项,浏览器的地址也变成login
            return redirect(url_for('first.login'))
        else:
            return render_template('register.html')

登陆模块:

# app.route 更改为blue来管理路由
@blue.route('/login/', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        if username == 'ququ' and password  == '123456':
            # res = make_response(render_template('index.html'))
            # res.set_cookie('token', '12345', max_age=100)
            # return res
            # 反向解析生成响应对象,然后设置token
            response = redirect(url_for('first.index'))
            response.set_cookie('token', '12345')
            return response
        else:
            return render_template('login.html')

之前写的相关跳转页面本质只是重新渲染,浏览器路由地址并非实现跳转,我们只是在html文件的form表单的action参数中配置成提交表单的跳转,改成url_for跳转的代码,则无需配置form表单的action参数。

反向解析的时候路由怎么传参数?

@blue.route('/redirect_func/')
def redirect_func():
    # url_for第二个参数是传给路由参数的值
    return redirect(url_for('first.s_id', id=6666))

@blue.route('/s_id/<int:id>/')
def s_id(id):
    return 's_id:%s'% id

三、模板

模板文件我们把它放在templates里面。

1、模板内容

基础模板,通俗说就是动态内容挖坑。

模版中的坑长成以下几种样子:

  • {{ ... }}:装载一个变量,模板渲染的时候,会使用传进来的同名参数这个变量代表的值替换掉。
  • {% ... %}:装载一个控制语句。
  • {# ... #}:装载一个注释,模板渲染的时候会忽视这中间的值。
2、创建base.html基础模板
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>
        {% block title %}
        {% endblock %}
    </title>
    {# 注意:模板名字不能重名 #}
    {% block css %}
    {% endblock %}

    {% block js %}
        {# 子模板公有的js文件放在这里 #}
    {% endblock %}
</head>
<body>
    {% block content %}
    {% endblock %}
</body>
</html>
3、继承基础模板的模板文件
{% extends 'base.html' %}

{% block js %}
    {{ super() }}
    <script src="23.js"></script>
{% endblock %}
{# 给子模板添加多个js #}

最终模板显示的顺序跟子模板的顺序跟父模板挖坑的顺序有关,跟子模板顺序无关。

父模板挖的坑,子模板不是所有的坑都要填,而是根据实际需求动态选择性地去填充父模板中定义的block的坑,{% block name%} 动态内容 {% endblock %}。

调用父模板中的内容,如果不调用super,则子模板会覆盖掉父模板中的内容。

4、引入静态文件

静态文件主要包括有CSS样式文件、JavaScript脚本文件、图片文件、字体文件等静态资源。

Jinja中加载静态文件只需要通过url_for全局函数就可以实现:

{% block css %}
    {# 引入样式的第一种写法 #}
    <link rel="stylesheet" href="/static/css/style.css">
    {# 引入样式的第二种写法 #}
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
{% endblock %}

改变静态文件之后,要清除浏览器的缓存,最新的样式才会显示出来。

5、后端返回数据

在渲染的时候就加参数,多个参数用逗号分隔。

@blue.route('/student/')
def stu():
    stus_scores = [90, 89, 100, 99, 87, 67]
    # stus_scores = []
    content_h2 = '<h2>你真的很棒!</h2>'
    return render_template('stu.html', scores=stus_scores, content_h2=content_h2)
6、变量

在模板中添加变量,可以使用(set)语句。

{% set name='xx' %}
7、控制语句
{% if 条件语句1 %}
    符合条件1显示的内容
{% elif 条件语句2 %}
    符合条件2显示的内容
{% else %}
    不符合条件1和条件2显示的内容
{% endif %}
8、for循环

1)普通用法

<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>

2)遍历字典

{% for key, value in my_dict.iteritems() %}
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
{% endfor %}

3)在循环中加入else

for 循环的变量users不存在或者users值为空,则执行else中的语句。

<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% else %}
<li><em>no users found</em></li>
{% endfor %}
</ul>

4)for循环中的变量

for循环中的变量都鞋子for循环里面

变量 说明
{{ loop.index }} 当前循环次数(从1开始)
{{ loop.index0 }} 当前循环次数(从0开始)
{{ loop.revindex }} 当前循环次数(倒序,以1结束)
{{ loop.revindex0 }} 当前循环次数(倒序,以0结束)
{{ loop.first }} 循环的第一次返回True,否则返回False
{{ loop.last }} 循环的最后一次返回True,否则返回False

注意:在Jinja2中不可以使用continue和break表达式来控制循环的执行。

4)Jinja2中for循环内置常量

代码 说明
loop.index 当前迭代的索引(从1开始)
loop.index0 当前迭代的索引(从0开始)
loop.first 是否是第一次迭代,返回True或者False
loop.last 是否是最后一次迭代,返回True或者False
loop.length 序列的长度
9、过滤器

过滤器是通过|符号进行使用的,例如:{{ name|length }}将返回name的长度。可以看成name是传入length函数的参数,然后过滤器根据自己的功能,再返回相应的值,之后再将结果渲染到页面中。

代码 说明
abs 返回一个数值的绝对值。示例:`{{ -1 abs }} `
length 返回一个序列或者字典的长度。示例:{{ msg|length }}
safe safe过滤器会使网页解析标签。示例:` {{content_html safe}} `。
default 如果当前变量没有值,则会使用参数中的值来代替。示例:`{{name default('xiaotuo')}}`
int 将值转换为int类型

自定义过滤器:

def mylen(arg):
    return len(arg)

env = app.jinja_env
# 给filters增加名为'mylen'的过滤器
env.filters['mylen'] = mylen

在模板文件文件中使用,mylen为过滤器名字,解析的时候找到对应的处理函数,把前面额msg当做参数传给对应的处理函数(在本例子中是mylen(arg))处理,最后返回的结果显示在页面上。

{{ msg|mylen }}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 228,546评论 6 533
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,570评论 3 418
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 176,505评论 0 376
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,017评论 1 313
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,786评论 6 410
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,219评论 1 324
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,287评论 3 441
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,438评论 0 288
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,971评论 1 335
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,796评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,995评论 1 369
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,540评论 5 359
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,230评论 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,662评论 0 26
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,918评论 1 286
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,697评论 3 392
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,991评论 2 374

推荐阅读更多精彩内容

  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 5,385评论 0 9
  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,424评论 0 5
  • 会员基本具备的特点: 1、有独有的尊享感 2、等级特权带来的优越感 3、能够带来优惠,福利 T——等级特权的优越感...
    好妹妹mango阅读 1,703评论 0 2
  • 原先总以为自己记性好,看过的东西,读过的文章,都会在自己脑子里留下一些印记。 起码,也是很多待触发的标志。 总会有...
    马_坤阅读 221评论 0 1
  • 人有喜怒哀乐,月有阴晴圆缺,生活五味杂陈,在对的时间遇到那个对的人,是一种眷顾。
    95后的年轻人阅读 96评论 0 0