flask3

作者: 遥远的她197 | 来源:发表于2019-03-07 18:31 被阅读0次

    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

    相关文章

      网友评论

          本文标题:flask3

          本文链接:https://www.haomeiwen.com/subject/rikhpqtx.html