flask3

hello.py文件是主页面,在开发时主页面不要写太多内容,所以我们要优化主页面。
创建一个app包,


image.png
__init__.py文件必须要有,有了这个py文件
才能把app文件当做一个库来使用
然后再创建一个views.py文件用来
存放hello.py文件中的路径文件
此时肯定会有很多的错误,
@app.route('/')不能跨文件,我们
就需要在Terminal下载一个蓝图文件
pip install Blueprint

# 蓝图, 管理路由地址
# 第一步:生成蓝图对象
blue = Blueprint('first', __name__)

然后再hello.py(主页面)
# app.views 此时它是一个库了
导入
from app.views import blue
此时必须把from hello import app删了, app已变成blue,
app不能跨文件,不删就会循环导入会报错

第二步:管理蓝图
app.register_blueprint(blueprint=blue)  # 注册一下

再回到views.py文件中
将所有的@app.route()改为
@blue.route()
再导入那些报红的库

views.py文件中
里面的redirect, url_for都是flask自带的, 导出来就行了

from flask import render_template, make_response, \
    request, session, Blueprint, redirect, url_for

# from hello import app 没用了 因为app已改成blue, app不能跨py文
# 件, 不删就会循环导入会报错
from utils.functions import is_login

# 蓝图, 管理路由地址
# 第一步: 生成蓝图对象
blue = Blueprint('first', __name__)


@blue.route('/')
def hello():
    return 'hello world'  # 这就是后端给前端的响应的内容


@blue.route('/make_res/')
def make_res():
    # make_response('响应内容', 响应状态码)创建响应对象 响应状态码默认为200
    # return make_response('hello flask day02', 200)
    # return make_response('<h2>今天天气不好</h2>')
    index = render_template('first.index')
    return make_response(index, 200)


@blue.route('/register/', methods=['GET', 'POST'])
def register():
    print(request.method)
    if request.method == 'GET':
        return render_template('register.html')
    if request.method == 'POST':
        # 模拟注册功能
        # 1.获取页面中传递的参数
        username = request.form.get('username')
        password = request.form.get('password')
        password2 = request.form.get('password2')
        # 模拟注册
        if username == 'coco' and password == password2 \
                and password == '123456':
            # 返回登录页面
            return redirect(url_for('first.login'))  # 同时跳转地址和页面
            # return render_template('login.html') # 跳转页面,但不会修改地址
        else:
            return render_template('register.html')


@blue.route('/login/', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    if request.method == 'POST':
        # 1.获取参数
        print(123)
        username = request.form.get('username')
        password = request.form.get('password')
        # 2.模拟登录
        if username == 'coco' and password == '123456':
            # 向cookie中设置参数 (钥匙)
            print('899')
            res = make_response(redirect(url_for('first.index')))
            # 设置cookie
            res.set_cookie('token', '12345678', max_age=3000)
            return res
        else:
            return render_template('login.html')


@blue.route('/logout/')
def my_logout():
    # 注销
    res = make_response(render_template('login.html'))
    res.delete_cookie('token')    # 删除key值
    return res


@blue.route('/index/')
def index():
    # 登录过后能看到index.html页面, 没有登录跳转到登录页面
    token = request.cookies.get('token')
    if token == '12345678':
        # 判断登录成功了
        return render_template('index.html')
    else:
        # 判断登录失败了
        return render_template('login.html')


@blue.route('/session_login/', methods=['GET', 'POST'])
def session_login():
    if request.method == 'GET':
        return render_template('session_login.html')

    if request.method == 'POST':
        # 解析参数
        username = request.form.get('username')
        password = request.form.get('password')
        if username == 'coco' and password == '123456':
            # 向session会话中设置键值对, 1代表True
            session['login_status'] = 1
            # session['name'] = 'coco'
            # session['pwd'] = '123456'
            return redirect(url_for('first.index'))
        else:
            return render_template('session_login.html')


@blue.route('/session_index/')
@is_login
def session_index():
    # if 'login_status' in session:

        return redirect(url_for('first.index'))
    # else:
    #    return render_template('session_login.html')


# 不用上面判断, 一步完成
@blue.route('/xindex/')
@is_login
def xindex():
    # 登录过后能够访问index.html页面
    # 没有登录不让访问,跳转到session.html页面
    return redirect(url_for('first.index'))


@blue.route('/session_logout/')
def session_my_logout():
    # 注销
    del session['login_status']
    # return render_template('session_login.html')  # 重新渲染下页面
    return redirect(url_for('first.session_login'))  # 和上面一样


# 跳转到一个函数
@blue.route('/redirect_func/')
def redirect_func():
    # 跳转到登录页面
    # return render_template('login.html')
    # return redirect('/login/')  # 跳转到这个地址上面, 类似昨天的action
    # url_for('蓝图第一个参数.跳转的函数名') 就可以不用写render_template()了
    # return redirect(url_for('first.login'))  # 蓝图第一个参数.函数名
    # 无参跳转
    # return redirect('/s_id/1/')
    return redirect(url_for('first.s_id', id=1))  # 和上一步一样
    # 的   这就是有参跳转


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


# 模板内容
@blue.route('/student/')
def stu():
    stus_score = [90, 89, 100, 99, 87, 67]
    content2_h2 = '<h1>睡觉</h1>'
    return render_template('stu.html', scores=stus_score, content2_h2=content2_h2)

上面文件中的is_login它是调用函数(为了简便,只在该页面需要一步操作,)
创建一个utils包,里面有init.py和functions.py文件
functions.py文件里是一个装饰器
functions.py文件中

from functools import wraps

from flask import session, render_template


# 装饰器
# 装饰器的三个条件:
# 1.外层函数嵌套内层函数
# 2.外层函数返回内层函数
# 3.内层函数调用外层函数的参数
# 下面最简单的装饰器结构:
def is_login(func):
    @wraps(func)  # 这步是让函数调用自己的本身(session_index),
而不是is_login
    def check():
 # 获取session是否登录那个值,假如没登录就异常捕获了,害怕报错
        try:
            session['login_status'] 
            # 登录过后能够访问index.html页面
            return func()
        except:
            # 没有登录不让访问,跳转到session.html页面
            return render_template('session_login.html')
    return check


if __name__ == '__main__':
    pass

优化完之后在hello.py文件中是这样的

import redis    # 这行是第三方库, 下面也是
from flask import Flask
from flask_script import Manager

from flask_session import Session

# from utils.functions import is_login  # 自己写的包(可以删掉了)
from app.views import blue

app = Flask(__name__)  # 生成app对象

# 第二步: 管理蓝图
app.register_blueprint(blueprint=blue)  # 注册一下

# 设置secret_key加密, 加密复杂程度和设置有关,不能告诉别人的
# 此时存在cookie中的
app.secret_key = '1234567890'
#  没有登录不让访问,跳转到session.html页面ession.html页面
# 配置session的信息
# from flask_session import Session
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = redis.Redis(host='127.0.0.1', port=6379)
Session(app)  # 会话

manage = Manager(app)

if __name__ == '__main__':
    # app.run()
    manage.run()

将导入的库变灰色的都删掉, 同时要导入

from app.views import blue  
# 因为用了app.register_blueprint(blueprint=blue)这句

二 优化html文件

jinja2
通过父模板来优化, 可以让多个html文件同时使用一个父模板,这样就免得写很多相同的页面和样式。

flask使用操作指南之模板
1. jinja2
Flask中使用jinja2模板引擎
jinja2是由Flask作者开发,模仿Django的模板引擎
优点:
速度快,被广泛使用

HTML设计和后端python分离

非常灵活,快速和安全

提供了控制,继承等高级功能

2. 模板语法
2.1 模板语法主要分为两种:变量和标签
模板中的变量:{{ var }}
视图传递给模板的数据

前面定义出来的数据

变量不存在,默认忽略

模板中的标签:{% tag %}
控制逻辑

使用外部表达式

创建变量

宏定义

2.2 结构标签:
block
{% block xxx %}

{% endblock %}

块操作
    父模板挖坑,子模板填坑

extends
{% extends ‘xxx.html’ %}

继承以后保留块中的内容
{{ super() }}

挖坑继承体现的化整为零的操作

macro

{% macro hello(name) %}

    {{ name }}

{% endmacro %}

宏定义,可以在模板中定义函数,在其他地方调用

宏定义可导入

{% from 'xxx' import xxx %}

例子1:

在index.html中定义macro标签,定义一个方法,然后去调用方法,结果是展示商品的id和商品名称

{% macro show_goods(id, name) %}
    商品id:{{ id }}
    商品名称:{{ name }}
{% endmacro %}

{{ show_goods('1', '娃哈哈') }}
<br>
{{ show_goods('2', '雪碧') }}

例子2:

在index.html页面中定义一个say()方法,然后解析该方法:

{% macro say() %}

    <h3>今天天气气温回升</h3>
    <h3>适合去游泳</h3>
    <h3>适合去郊游</h3>

{% endmacro %}

{{ say() }}

例子3:

定义一个function.html中定义一个方法:

{% macro create_user(name) %}
    创建了一个用户:{{ name }}
{% endmacro %}

在index.html中引入function.html中定义的方法

{% from 'functions.html' import create_user %}

{{ create_user('小花') }}

2.3 循环

{% for item in cols %}

    aa

{% else %}

    bb

{% endfor %}

也可以获取循环信息loop

loop.first

loop.last

loop.index

loop.revindex

2.4 过滤器

语法:

{{ 变量|过滤器|过滤器... }}

capitalize 单词首字母大写
lower 单词变为小写
upper 单词变为大写
title
trim 去掉字符串的前后的空格
reverse 单词反转
format
striptags 渲染之前,将值中标签去掉
safe 讲样式渲染到页面中
default
last 最后一个字母
first
length
sum
sort

例子:
<ul>
    <li>{{ content_h2 }}</li>
    <li>{{ content_h2|safe }}</li>
    <li>{{ content_h2|striptags }}</li>

    <li>{{ content_h3 }}</li>
    <li>{{ content_h3|length }}</li>
    <li>{{ content_h3|trim|safe }}</li>
    <li>{{ content_h3|trim|length }}</li>
</ul>

3. 定义模板

3.1 定义基础模板base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>
        {% block title %}
        {% endblock %}
    </title>
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>

    {% block extCSS %}
    {% endblock %}
</head>
<body>

{% block header %}
{% endblock %}

{% block content%}
{% endblock %}

{% block footer%}
{% endblock %}

{% block extJS %}
{% endblock %}

</body>
</html>

3.2 定义基础模板base_main.html

{% extends 'base.html' %}

{% block extCSS %}
    <link rel="stylesheet" href="{{ 
url_for('static', filename='css/mai
n.css') }}">
{% endblock %}

首先我们在templates创建base.html文件, base_main.html文件
base.html文件中

<!--此时这个页面是个框架, 父模板-->
<!--父模板挖坑, 子模板没必要都要填坑-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>
        <!--jinja2 title是命名 俗称挖坑-->
        {% block title %}
        {% endblock %}
    </title>
    {% block css %}
    {% endblock %}

    {% block js %}
    {% endblock %}
</head>
<body>
      <!--content是命名-->
      {% block content %}
       {% endblock %}
</body>
</html>

base_main.html文件中

{% extends 'base.html' %}
<!--继承某个模板-->
<!--让每个页面都引用下面这个js-->

{% block js %}

   <!--初始化引入juquery.js-->
   <script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
{% endblock %}

stu.html页面

<!--继承 网页上显示的是下面的页面的而不是stu了-->
<!--先继承 再填坑, 子模板没必要都填坑,没用就不填-->
<!--坑的名字必须唯一-->
<!--{{ a }} 就是在html上打印a 里面a是变量-->
{# {{ 注释 }} #}
{% extends 'base_main.html' %}



{% block title %}
  学生列表页面
{% endblock %}

{% block css %}
        <!--第一种写法-->
       <!--<link rel="stylesheet" href="/static/css/style.css">-->
       <!--第二种写法-->
       <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
{% endblock %}

{% block js %}
       {{ super() }}
       <script src="23231dewdde.js"></script>
       {# {{ 此时不会显示base_main里面的js,因为只显示这个, 当加了{{ super() }}之后两个都会显示 }} #}
{% endblock %}

{% block content %}
     <!--过滤器 | - 管道符  safe-加载样式 striptags取消标签-->
     <p>{{ content2_h2 | safe }}</p>
     <p>{{ 'Python' | length }}</p>
     <p>{{ 'Python' | upper }}</p>
     <p>{{ 'Python' | lower }}</p>
      <p>{{ 'Python' | upper | length }}</p>
      <p>{{ 'Python' | reverse }}</p>
      <p>{{ content2_h2 | striptags }}</p>

     <!--解析变量使用 {{ 变量名 }}-->
     <p> {{ scores }} </p>

     <!--解析标签, extends, block, for-->
     <ul>
         {% for a in scores %}
             <!--显示列表的数字-从0开始(类似于下标)  revindex倒着排序-->
             {{ loop.index0 }}
             <!--判断是否为第一个(是就为True,不是则为False)和最后一个-->
             {{ loop.first }}
             {{ loop.last }}
             <li {% if loop.first == 1 %} style="color:yellow;" {% endif %}>
                 {{ a }}
             </li>
         {% else %}
             <li>没有学生成绩数据</li>
         {% endfor %}

     </ul>
<table>
     <thead>
         <th>姓名</th>
         <th>年龄</th>
     </thead>
     <tbody>
            <tr>
             <td>张三</td>
             <td>28</td>
             </tr>
            <tr>
                <td>李四</td>
                <td>29</td>
            </tr>
     </tbody>
</table>
{% endblock %}

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

推荐阅读更多精彩内容

  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom阅读 2,694评论 0 3
  • 1. 对学生数据进行CRUD操作 语法: 获取查询集: 数据操作: 1.1 想学生表中添加数据 提交事务,使用co...
    晓晓的忍儿阅读 510评论 0 0
  • (一)、启动服务器 (二)、创建数据库表 或 更改数据库表或字段 Django 1.7.1及以上 用以下命令 1....
    夏天夏星阅读 5,653评论 0 17
  • 随着天气暖和,减肥的节奏就疯狂起来~ 看到这张图,是不是有了减肥的斗志?! 我们感官最容易被美好的事物所冲击,我们...
    甜甜姐Sweety阅读 412评论 0 0
  • 今晚在休斯顿丰田中心现场看了人生中的首场NBA比赛,火箭VS老鹰。 6点左右的时候,我们还在逛沃尔玛,最后决定去看...
    一條猪阅读 550评论 0 0