Flask框架基础学习二

Flask框架基础学习二

请求钩子

  1. before_first_request: 服务启动,第一个用户第一次访问,会调用此方法。
  2. before_request: 请求处理之前调用
  3. after_request: 处理请求之后调用
  4. teardown_request: 如果有异常就触发,会传递错误异常参数(只有DEBUG=False时才会生效)
from flask import Flask

app = Flask(__name__)


class Config:
    DEBUG = False


app.config.from_object(Config)


@app.before_first_request
def before_first_request():
    # 服务启动,第一个用户第一次访问,会调用此方法
    # 实现一些初始化操作,例如连接数据库
    print("before_first_request")


@app.before_request
def before_request():
    # 请求操作处理之前调用
    # 基于权限对应的操作
    print('before_request')


@app.after_request
def after_request(response):
    # 处理请求之后调用
    # 记录操作记录,清理收尾工作
    print('after_request')
    # 必须返回response
    return response


@app.teardown_request
def teardown_request(e):
    # 如果有异常触发,则会传递错误异常e
    print(e)
    return e


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


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

异常捕获

  • 抛出异常: abort

    • 导入: from flask import abort
    • 使用: abort(状态码)
  • 捕获异常

    • 使用: @app.errorhandler(状态码)
  • 完整代码

    • from flask import Flask, abort
      
      app = Flask(__name__)
      
      
      class Config:
          DEBUG = True
      
      
      app.config.from_object(Config)
      
      
      @app.route('/index/<int:num>')
      def index(num):
          if num > 10:
              return 'ok'
          else:
              abort(404)  # 抛出404
      
      
      @app.errorhandler(404)  # 捕获404这个异常
      def err(e):
          print(e)
          return '<h1>错误页面</h1>'  # 返回html页面或者html代码
      
      
      if __name__ == '__main__':
          app.run()
      
      

context上下文

  • 请求上下文

    • request
      • 封装了HTTP请求的内容。例如: request.args/request.form
    • session
      • 记录了请求会话中的信息。例如: session['name']/session.get('name')
  • 应用上下文

    • current_app

      • 导入: from flask import current_map

      • 当不知道实例化flask对象名称时,可以使用current_app来代替flask对象名

      • from flask import Flask, current_app
        
        app = Flask(__name__)
        
        
        class Config:
            DEBUG = True
        
        
        app.config.from_object(Config)
        
        
        @app.route('/')
        def index():
            print(app.config)
            print(app.url_map)
            
            # 以下输出是跟上面app.config和app.url_map输出一样的,当我们不清楚app叫什么的时候,可以使用current_app
            print(current_app.config)
            print(current_app.url_map)
            return 'ok'
        
        
        if __name__ == '__main__':
            app.run()
        
    • g

      • 导入: from flask import g

      • g是flask程序全局的一个临时变量,通过它可以传递一些数据。

      • from flask import Flask, g
        
        app = Flask(__name__)
        
        
        class Config:
            DEBUG = True
        
        
        app.config.from_object(Config)
        
        
        @app.before_request
        def before_request():
            g.name = 'aaa'  # 全局范围的一个变量
        
        
        @app.route('/')
        def index():
            print(g.name)  # aaa,在函数中可以调用此变量并使用
            return 'ok'
        
        
        if __name__ == '__main__':
            app.run()
        
  • 两者区别

    • 请求上下文: 保存了客户端和服务器交互的数据等。
    • 应用上下文: 保存了flask程序运行过程中的一些配置信息和应用信息等。

Flask-Script扩展(终端脚本工具)

  • 安装: pip install flask-script

  • 使用flask-script启动flask应用

    • from flask import Flask
      from flask_script import Manager
      
      
      app = Flask(__name__)
      
      """使用flask_script启动项目"""
      manage = Manager(app)
      
      @app.route('/')
      def index():
          return 'hello'
      
      if __name__ == "__main__":
          manager.run()
      
      # 终端命令
      python run.py runserver  # 不写域名和端口,默认是127.0.0.1和5000
      # 通过-h设置启动域名,-p设置启动端口
      python run.py runserver -h127.0.0.1 -p5000
      
  • 自定义脚本命令

    • # main.py
      import os
      
      from flask import Flask
      from flask_script import Manager, Command, Option
      
      app = Flask(__name__)
      
      
      class Config:
          DEBUG = True
      
      
      app.config.from_object(Config)
      
      manager = Manager(app)
      
      
      class BluePrinter(Command):
          option_list = [
              Option('--filename', '-f', help="提示"),  # 自定义命令: 参数一是全称,参数二是简称
              Option('--name', '-n', help="提示")  # 可以指定多个参数
          ]
      
          def run(self, filename=None, name=None):  # 这边的形参必须和上述参数一致
              if filename is None:
                  return
      
              if not os.path.exists(filename):
                  # 没有文件夹的情况下
                  os.mkdir(filename)
      
              open(f'{filename}/views.py', 'w', encoding='utf-8')
              open(f'{filename}/models.py', 'w', encoding='utf-8')
              with open(f"{filename}/urls.py","w", encoding='utf-8') as fp:
                  fp.write("""from . import views
      urlpatterns = [
      
      ]
      """)
      
      
      
      manager.add_command('blue', BluePrinter)  # 定义命令名称
      
      if __name__ == '__main__':
          manager.run()
      
      # 执行(python 文件名 命令名 指令命令=参数)
      # python main.py blue --filename=users
      # python main.py blue -f=users
      
      

jinja2模板引擎

基本使用

  • 视图函数传参: render_template("index.html", name=name, info=info)
  • 模板接收参数: <p>{{ name }} {{ info }}</p>

视图代码

# main.py
from flask import Flask, render_template

app = Flask(__name__)


class Person:

    def __init__(self, name, age):
        self.name = name
        self.age = age


@app.route('/')
def index():
    name = 'bbb'
    hobby = ['game', 'music', 'book']
    info = {
        'age': 24,
        'sex': True
    }
    p = Person('aaa', 24)

    data = [
        {"id": 1, "price": 78.50, "title": "书本1"},
        {"id": 5, "price": 88.50, "title": "书本2"},
        {"id": 3, "price": 98.50, "title": "书本3"},
        {"id": 2, "price": 71.50, "title": "书本4"},
        {"id": 7, "price": 63.50, "title": "书本5"},
        {"id": 6, "price": 58.50, "title": "书本6"},
    ]

    dic = {
        'name': name,
        'hobby': hobby,
        'info': info,
        'person': p,
        'data': data
    }

    return render_template('index.html', **dic)


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

模板代码

# 模板代码
<div>
    {{ name }}  <!-- bbb -->
    {{ hobby[0] }}   <!-- game -->
    {{ info.age }}   <!-- 24 -->
    {{ person.age }}  <!-- 24 -->

    <table border="1">
        <thead>
        <tr>
            <th>序号</th>
            <th>ID</th>
            <th>价格</th>
            <th>名称</th>
        </tr>
        </thead>
        <tbody>
        {% for i in data %}
            <tr>
                <td>{{ loop.index }}</td>
                <td>{{ i.id }}</td>
                {% if i.price > 70 %}
                    <td>{{ i.price }},还是太贵了</td>
                {% else %}
                    <td>{{ i.price }},价格比较便宜</td>
                {% endif %}
                <td>{{ i.title }}</td>
            </tr>
        {% endfor %}
        </tbody>
    </table>

<!--
序号 	ID 	价格 	              名称
1 	  1  78.5,还是太贵了     书本1
2 	  5  88.5,还是太贵了     书本2
3 	  3  98.5,还是太贵了     书本3
4     2  71.5,还是太贵了     书本4
5 	  7  63.5,价格比较便宜   书本5
6 	  6  58.5,价格比较便宜   书本6	
-->
    
    {{ request.method }}    <!-- GET -->
    {{ session }}			<!-- session对象 -->
    {{ url_for('index') }}  <!-- /(index视图函数对应的URL) -->
</div>
  • for循环中的一些特殊变量
变量描述
loop.index循环的次数(从1开始)
loop.index0循环的次数(从0开始)
loop.revindex到循环结束还差几次(从0开始)
loop.revindex0到循环结束还差几次(从1开始)
loop.first当此次是第一次循环,则为True,反之则为False
loop.last当此次是最后一次循环,则为True,反之则为False
loop.length循环序列的长度

过滤器

字符串操作

指令解释
safe转义
capitalize首字母大写,其他小写
lower字符串全部小写
upper全部大写
title值中的每个单词的首字母都转成大写
reverse字符串反转
format‘%s in %s’ | format(“a”, “aaa”) 格式化输出
striptags渲染之前将html标签都删除(遇到>或<在内容中会有歧义)
truncate字符串截断

列表操作

指令解释
first取列表的第一个元素
last取列表的最后一个元素
length获取列表的长度
sum求列表的总和
sort列表排序(从小到大)

语句块

{% filter upper %}
	aaaaa
    bbbbb
    ccccc
{% endfilter %}

"""
结果:
	AAAAA
    BBBBB
    CCCCC
"""

自定义过滤器

# 需求: 将列表反转再拼接成字符串

# 方式一
def reverse(old):
    new_list = list(old)
    new_list.reverse()
    new_string = ''.join(new_list)
    return new_string

app.add_template_filter(reverse, 'rev_join')  # 这里添加

# 方式二
@app.template_filter('rev_join')  # 这里添加
def reverse(old):
    new_list = list(old)
    new_list.reverse()
    new_string = ''.join(new_list)
    return new_string


# 使用: {{ ["a", "b", 'c', 'd'] | rev_join }}  --> dcba


# 案例: 将手机号只保留前三位和后四位  13222999000 --> 132****9000
@app.template_filter('hide_phone')  # 这里添加
def reverse(phone, hide_string):
    p_str = phone[:3] + hide_string + phone[-4:]
    return p_str

# 使用: {{ "13222929986" | hide_phone("****") }}  --> 132****9986

模板继承

base.html

{# 创建一个base.html作为模板 #}
<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="{{ url_for('static',filename='./css/style.css') }}">
    {# 创建一个static文件夹用来放静态文件,filename指向的静态文件就是从这个static开始往下 #}
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    <div id="head">
		<h1>头部</h1>
    </div>
   

{% block main %}    {# 声明一个块 #}
    <div id="main">
        <h4>这是base页面</h4>
    </div>
{% endblock %}


    <div id="footer">
        <h4>底部</h4>
    </div>

</body>

</html>

index.html

{% extends "base.html" %}  {# 继承模板 #}

{% block main %}
	{{ super() }}  {# 当使用super时,可以将模板中这一块的代码也显示出来 #}
    <div id="main">
        <h4>这是index页面</h4>
    </div>
{% endblock %}

当用户查看index页面时,输出下面代码

<body>

    <div id="head">
		<h1>头部</h1>
    </div>
   
    <!-- 当使用super的时候这里注释的代码也会显示出来,因为它是模板中这一块的代码
        <div id="main">
            <h4>这是base页面</h4>
        </div>
	-->    

    <div id="main">
        <h4>这是index页面</h4>
    </div>


    <div id="footer">
        <h4>底部</h4>
    </div>

</body>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值