Flask之最易懂的基础教程


本文由 简悦 SimpRead 转码, 原文地址 blog.csdn.net

Flask 框架的基础教程:

一、web 工作原理

1. B/S 和 C/S 架构
- B/S:浏览器/服务器架构(客户端需要更新才行)
- C/S:客户端/服务器架构(刷新页面即可更新)(可能会成为主流)
2. WEB 工作原理
客户端 > 服务器 > python(flask) > 数据库(mysql)

二、Flask 框架

1. 简介
  • 是一个非常小的框架,可以称为微型框架,只提供了一个强劲的核心,其他的功能都需要使用拓展来实现。意味着可以根据自己的需求量身打造;
2. 组成
  • 调试、路由、wsgi 系统
  • 模板引擎 (Jinja2)
3. 安装
  • pip install flask
4. 简单使用
  • 创建 Flask 框架。(社区版没有直接创建的功能,专业版有)
# 导入Flask类库
from flask import Flask
# 创建应用实例
app = Flask(__naem__)
# 视图函数(路由)
@app.route('/')
def index():
    return '<h1>Hello Flask!<h1>'
# 启动实施(只在当前模块运行)
if __name__ == '__main__':
    app.run()
5. run 方法参数
参数说明默认值
debug代码更新是否自动重启False
theaded是否开启多线程False
port指定端口5000
host指定主机(设置 0.0.0.0 可以通过本地 IP 访问)127.0.0.1
6. 请求和响应
变量上下文描述
current_app应用上下文相当与在主程序中激活的实例化 app(app=Flask(__name__)
g应用上下文一次性函数,处理请求的临时变量。只在一个请求中被应用,下个请求开始时会自动重置
request请求上下文请求对象。存放了客户端发来的 HTTP 信息
session请求上下文记录用户和服务器之间的会话的。在服务器端记录需要记住的信息。(和 cookie 对应,cookies 是记录在客户端的)
7. 请求钩子装饰器
函数描述
before_first_request第一次请求之前
before_request每次请求之前
app.after_request没有异常,每次请求结束后
app.teardown_request有异常也会运行,每次请求结束后

说明:以上钩子函数若写在蓝图中,只能针对蓝本的请求。若想在蓝本中设置全局有效的函数,需要使用带 app 的钩子函数。如:before_first_request 变为 before_app_first_request。

8. 视图函数
1. 不带参数的视图函数
# 导入Flask类库
from flask import Flask
# 创建应用实例
app = Flask(__name__)
# 视图函数(路由)
@app.route('/index')
def index():
    return '<h1>Hello Flask!<h1>'
# 启动实施(只在当前模块运行)
if __name__ == '__main__':
    app.run()
2. 带参数的视图函数
# 导入Flask类库
from flask import Flask
# 创建应用实例
app = Flask(__name__)
# 视图函数(路由)
@app.route('/user/<username>')
def say_hello(username):
    return '<h1>Hello %s !<h1>' % username
# 启动实施(只在当前模块运行)
if __name__ == '__main__':
    app.run()
  1. 参数要写在 <> 中、
  2. 视图函数的参数要与路由中的一致
  3. 也可以指定参数类型(int/float/path),默认是字符串
3. 带类型限定(path)的视图函数
# 导入Flask类库
from flask import Flask
# 创建应用实例
app = Flask(__name__)
# 视图函数(路由)
@app.route('/user/<path:info>')
def test(info):
    return info
# 启动实施(只在当前模块运行)
if __name__ == '__main__':
    app.run()

前端运行结果:

  1. 路由中最后的 "/" 最好带上,否在访问时可能会报错。
9. 获取 request 请求值
# 导入Flask类库
from flask import Flask,request
# 创建应用实例
app = Flask(__name__)
# request
@app.route('/request/<path:info>')
def request_url(info):
    # 完整的请求URL
    return request.url
    '''
    url:127.0.0.1:5000/request/abc/def?username=xiaoming&pwd=123
    网页返回值:http://127.0.0.1:5000/request/abc/def?username=xiaoming&pwd=123
    '''
    # 去掉GET参数的URL
    return request.base_url
    '''
    网页返回值:http://127.0.0.1:5000/request/abc/def
    '''
    # 只有主机和端口的URL
    return request.host_url
    '''
    网页返回值:http://127.0.0.1:5000/
    '''
    # 装饰器中写的路由地址
    return request.path
    '''
    网页返回值:/request/abc/def
    '''
    # 请求方法类型
    return request.method
    '''
    网页返回值:GET (也有可能时POST)
    '''
    # 远程地址
    return request.remote_addr
    '''
    网页返回值:127.0.0.1:5000
    '''
    # 获取url参数
    return request.args.get('username')
    return request.args.get('pwd')
    return str(request.args)
    # 获取headers信息
    return request.headers.get('User-Agent')
# 启动实施(只在当前模块运行)
if __name__ == '__main__':
    app.run()
10. 响应的构造(make_response)
from flask import Flask,make_response
app = Flask(__name__)
@app.route('/response/')
def response():
    # 不指定状态码,默认为200,表示OK
    # return ‘OK’
    # 构造一个404状态码
    # 方法一
    return 'not fount',404
    # 方法二
    # 导入make_response
    # 自定义构造一个响应,然后返回200,构造也可以指定状态码404
    res = make_response('我是通过函数构造的响应',404)
    return res
if __name__ == '__main__':
    app.run()
11. 重定向(redirect)
from flask import Flask,redirect
app = Flask(__name__)
@app.route('/old/)
def old():
    # return '这里是原始内容。'
    # 如果输入旧的old路由,会指向新的地址。
    # 先输入一个外地请求试试
    return redirect('https://www.baidu.com')
    # 再输入一个本地请求试试
    return redirect('/new/')
    # 根据视图函数找到路由,指向方法:<url_for>中的参数'new'指向的是<函数名>
    return redirect(url_for('new'))
    return redirect(url_for('say_hello',username='xiaoming'))
@app.rout('/new/')
def new():
    return '这里是新的内容'
if __name__ == '__main__':
    app.run()
12. 终止 abort
from flask import Flask
app = Flask(__name__)
@app.route('/login/')
def login():
    # return '欢迎登录'
    # 此处使用abort可以主动抛出异常
    abort(404)
if __name__ == '__main__':
    app.run()
13. 会话控制 cookie 和 session(附加过期时间的设置)
1. 会话控制 cookie
# 发送到response的headers里面(客户端)
from flask import Flask
import time
app = Flask(__name__)
@app.route('/set_cookie/')
def set_cookie():
    resp = make_response('设置cookie')
    # 指定过期时间
    expires = time.time + 10
    resp.set_cookie('name','xiaoming',expires=expires)
    return resp
if __name__ == '__main__':
    app.run()
# 发送到request的headers里面(服务器)
# 如果清除cookie后,会导致name=xiaoming的cookie被清除。
# 那么就会在网页显示'你是哪个?'
from flask import Flask,request
app = Flask(__name__)
@app.route('/get_cookie/')
def get_cookie():
    return request.cookie.get('name') or '你是哪个?'
if __name__ == '__main__':
    app.run()
2. 会话控制 session
# 发送到response的headers里面(客户端)
from flask import Flask,session
import time,os
'''
这里可以给SECRET_KEY设置一个随机N位字符串:os.urandom(n)
'''
app = Flask(__name__)
# 设置一个随机18位字符串的密钥,也可以设置成固定字符串
app.config['SECRET_KEY'] = os.urandom(18)
# app.config['SECRET_KEY'] = '这是个密钥字符串'
@app.route('/set_session/')
def set_session():
    # session本身是个字典,需要直接添加键值对
    '''
    添加session值之前,必须先设置SECRET_KEY
    '''
    session['username'] = 'xiaoqiao'
    return 'session已设置'
@app.route('/get_session/')
def get_session():
    # 获取session中的username的值,否则返回'who are you ?'
    return session.get('username','who are you ?')
if __name__ == '__main__':
    app.run()
14. 命令行控制启动
  1. 安装
    pip install flask-script

  2. 使用

    # 导入类库
    from flask_script import Manager
    app = Flask(__name__)
    # 创建对象
    manager = Manager(app)
    # 启动程序
    if __name__ == '__main__':
        # app.run()
        # 命令行控制启动
        manager.run()
    
  3. 参数:

    启动:python manager.py runserver [-d] [-r]
    -? & --help 查看帮助
    -d          开启调试模式
    -r          修改文件自动加载
    -h --host   指定主机
    -p --port   指定端口
    --threaded  使用多线程     
    
  4. 详情参考:https://blog.csdn.net/weixin_45950544/article/details/104047350

15.Flask 模板
1. 模板介绍:
  • 结构清晰、易于维护的代码开发原则是程序员追求的目标之一。目前我们所写的代码都比较简单,但是很明显的可以预见的一个问题是,当项目越来越复杂时,视图函数将变得异常庞大和繁琐,因为视图函数中存放了业务逻辑和表现逻辑。
  • 解决这类问题的通用方法是将不同种类的逻辑分开存放:
    • 业务逻辑:存放在视图函数中,专门处理用户的业务需求;
    • 表现逻辑:存放在单独的模板文件夹中,负责表现效果。
2. 模板引擎
  • 指定了一套特定的语法来实现表达逻辑,提供了一种专门的替换接口将模板文件换成目标文件(html)。——flask 中提供了专门的模板引擎(jinja2)
3. JinJa2(解析参数)
  • manager.py

    from flask import Flask,render_template,render_template_string,g
    from flask_script import Manager
    app = Flask(__name__)
    manager = Manager(app)
    @app.route('/index')
    def index():
        # return '模板引擎测试'
        # 渲染模板文件
        return render_template('index.html')
    @app.route('/index')
    def welcome('/index/<name>'):
        # 变量参数写在渲染函数的后面作为参数,前面的name是形参,后面的name是渲染模板中的解析内容
        # return render_template('index.html',name=name)
        # 第二种方法,使用render_template_string(渲染字符串)
        # return render_template_string('<h2>hello {{ name }} ! <h2>',name=name)
        # 第三种方法,使用  g(全局函数),不需要分配就可以在模板中使用,
        # 只需要给定渲染模板即可;
        g.name = name
        return render_template('index.html')
    if __name__ == '__main__':
        manager.run()
    
  • templates(存放模板文件夹)/index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>模板</title>
    </head>
    <body>
        <h1>模板引擎测试</h1> 
        { # {{ }} 括号中的内容将被解析 # }
        <h2> hello {{ name }} ! </h2>
        <h3> hello {{ g.name }} ! </h3>
    </body>
    </html>
    
4. 使用函数
  1. 在要解析的变量的后面添加一个‘ | ’
  2. 在‘ | ’的后面添加一个需要处理的函数
5. 常用函数
函数说明
capitalize首字母大写
upper全部大写
lower全部小写
title每个单词首字母大写
trim去掉两边的空白
striptags去掉所有的 HTML 标签
safe即删除标签,又保留标签功能
  • manager.py

    from flask import Flask,render_template
    from flask_script import Manager
    app = Flask(__name__)
    manager = Manager(app)
    @app.route('/index')
    def welcome('/index/<name>'):
        # 变量参数写在渲染函数的后面作为参数,
        # 前面的name是形参,后面的name是渲染模板中的解析内容
        return render_template('index.html',name=name)
    if __name__ == '__main__':
        manager.run()
    
  • templates(存放模板文件夹)/index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>模板</title>
    </head>
    <body>
        <h1>hello {{ name|capitalize }} ! </h1> 
    </body>
    </html>
    
  • 在网页上输入127.0.0.1:5000/index/xiaoming

  • 网页显示如下:

  1. manager.py

    from flask import Flask,render_template
    from flask_script import Manager
    app = Flask(__name__)
    manager = Manager(app)
    @app.route(/usefunc/)
    def ues_func():
        return render_template('use_func.html',var='hanmeimei')
        return render_template('use_func.html',var='<b>xiaoming</b>')
    if __name__ == '__main__':
        manager.run()
    
  2. templates(存放模板文件夹)/use_func.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>模板</title>
    </head>
    <body>
        <h1>hello {{ var|capitalize }} ! </h1>
        {# 将有<b>xiaoming</b>的标签删除 #}
        hello {{ var | striptags }} ! 
        {# 即删除标签,又保留标签功能#}
        hello {{ var | safe }} ! 
    </body>
    </html>
    
  3. 网页内容显示如下:

6. 控制结构
  1. manager.py

    from flask import Flask,render_template
    from flask_script import Manager
    app = Flask(__name__)
    manager = Manager(app)
    @app.route(/control/)
    def control():
        # 分配了该怎么处理,没有分配该怎么处理
        return render_template('control.html',name='xiaoming')
    if __name__ == '__main__':
        manager.run()
    
  2. templates(存放模板文件夹)/control.html

    1. if…else 语句
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>模板</title>
    </head>
    <body>
        {# 判断显示内容 #}
        {# 如果分配了name的内容 #}
        {% if name %}
            <h1>hello {{ name|capitalize }} ! </h1>
        {# 如果不分配 #}
        {% else %}
        <h1>请登录</h1>
        {% endif %}
    </body>
    </html>
    
    1. for 语句
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>模板</title>
    </head>
    <body>
        <ol>
            {% for x in range(1,5) %}
                {# 光显示 x 是不行的,因为没有进行解析。#}
                {# 需要对 x 进行解析,用{{ }} #} 
                <li> {{ x }} </li>
            {% endfor %}
        </ol>
    </body>
    </html>
    
7. 宏的使用
  • 基础使用方法:(类似于自定义函数)

    1. manager.py

      from flask import Flask,render_template
      from flask_script import Manager
      app = Flask(__name__)
      manager = Manager(app)
      @app.route(/macro/)
      def macro():
          return render_template('macro.html',name='xiaoming')
      if __name__ == '__main__':
          manager.run()
      
    2. templates(存放模板文件夹)/macro.html

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>模板</title>
      </head>
      <body>
          {# 这里是设置宏 #}
          {% macro show(name) %}
              <h1>This is {{name}}</h1>
          {% endmacro %}
          {# 下面是调用宏 #}
          {{ show(name) }}
      </body>
      </html>
      
  • 集中定义宏并在其他文件中调用:(将宏单独存放在一个文件中)

    1. manager.py(不变)

      from flask import Flask,render_template
      from flask_script import Manager
      app = Flask(__name__)
      manager = Manager(app)
      @app.route(/macro/)
      def macro():
          return render_template('macro.html',name='xiaoming')
      if __name__ == '__main__':
          manager.run()
      
    2. 文件一:设置宏
      templates(存放模板文件夹)/macro2.html

          {# 这里是设置宏 #}
          {% macro welcome(name) %}
              <h1>This is {{name}}</h1>
          {% endmacro %}
      
    3. 文件二:调用宏
      templates(存放模板文件夹)/macro.html

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>模板</title>
      </head>
      <body>
          {# 下面是调用宏 #}
          {% from 'macro2.html' import welcome %}
          {{ welcome(name) }}
      </body>
      </html>
      
8. 文件包含
  1. manager.py

    from flask import Flask,render_template
    from flask_script import Manager
    app = Flask(__name__)
    manager = Manager(app)
    @app.route(/include/)
    def include():
        return render_template('include.html',name='xiaowang')
    if __name__ == '__main__':
        manager.run()
    
  2. 文件一:设置宏
    templates/macro2.html

    {# 这里是设置宏 #}
    {% macro welcome(name) %}
        <h1>This is {{name}}</h1>
    {% endmacro %}
    
  3. 文件二:调用宏
    templates/macro.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>模板</title>
    </head>
    <body>
        {# 下面是调用宏 #}
        {% from 'macro2.html' import welcome %}
        {{ welcome(name) }}
    </body>
    </html>
    
  4. 文件三:收录方法 (类似拷贝文件)
    templates/include.html

    {% include 'macro.html' %}
    
9. 模板继承
  • 首先,要有一个父类模板;
  • 然后,需要让子类模板继承父类模板;
  • 最后,写一个测试的路由,渲染子类模板。
  1. 文件一:创建父类模板
    templates/parents.html

    {# 写一个块(block) #}
    <html>
    <head>
        {% block head %}
        <title>
            {% block title %}
            默认标题
            {% endblock %}
        </title>
        {% endblock %}
    </head>
    <body>
        {% block body %}
        默认内容
        {% endblock %}
    </body>
    </html>
    
  2. 文件二:创建子类模板
    templates/children.html

    • 继承父类模板,并可以在继承基础上重写父类
    • 继承父类模板,保留原有父级模板中的内容
    {# 继承自parents模板 #}
    {% extends 'parents.html' %}
    {# 指定块,重写父类 #}
    {% block title %}首页{% endblock %}
    {% block head %}
        {# 保留原有父级模板中的内容 #}
        {{ super }}
        <h1>添加的内容</h1>
    {% endblock %}
    {# 删除基础模板中的指定块 #}
    {% block body%} {% endblock %}
    

    extends方法与include方法有所不同,include方法照搬过来的时候,不能进行重写等操作,而extends方法可以做到。

  3. 文件三:写一个测试的路由,渲染子类模板
    manager.py

    from flask import Flask,render_template
    from flask_script import Manager
    app = Flask(__name__)
    manager = Manager(app)
    @app.route(/extends/)
    def extends():
        return render_template('children.html')
    if __name__ == '__main__':
        manager.run()
    

16. 使用 bootstrap(基础模板引用)
1. 安装

pip install bootstrap

2. 使用
  1. bootstrap.py

    from flask_bootstrap import Bootstrap
    app = Flask(__name__)
    bootstrap= Bootstrap(app)
    @app.route(/bootstrap/)
    def bootstrap():
        return render_template('bootstrap.html',name='xiaoming')
    if __name__ == '__main__':
        manager.run()
    
  2. templates/bootstrap.html

    {# 继承自bootstrap的基础模板 #}
    {% extends 'bootstrap/base.html' %}
    
    {# 写标题 #}
    {% block title %}bootstrap测试{% endblock %}
    {# 写内容 #}
    {% block content %}
    <div class='container'>
        <h1>Hello {{name}} </h1>
    </div>
    {% endblock %}
    
  3. bootstrap 的基础模板中定义了很多 block,可以在衍生模板中直接使用

    块名说明
    doc整个文档
    htmlhtml 标签中的内容
    headhead 标签的内容
    titletitle 标签的内容
    bodybody 标签的内容
    metas一组 metas 标签
    styles层叠样式表
    scripts加载 Js 代码
    content自定义内容
    navbar定义导航条

    说明:上述的 block 在子模板中都可直接使用,但是可能会出现覆盖问题,当出现问题时,很多时候都是因为没有调用 super()

3. 基础模板定制
  • 继承 bootstrap, 自定义 base 模板
  1. templates/base.html

    {# 继承自bootstrap的基础模板 #}
    {% from bootstrap/base.html %}
    {% block title %}博客{% endblock %}
    {% block navbar %}
    <nav style='border-radius:0px;'>
       <div>
           <!-- Brand and toggle get grouped for better mobile display -->
           <div>
               <button type="button" data-toggle="collapse"
                       data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                   <span>Toggle navigation</span>
                   <span></span>
                   <span></span>
                   <span></span>
               </button>
               <a href="#">首页</a>
           </div>
    
            <!-- Collect the nav links, forms, and other content for toggling -->
            <div>
                <ul>
                    <li><a href="#">板块一</a></li>
                    <li><a href="#">板块二</a></li>
                </ul>
                <ul>
                    <li><a href="#">登录</a></li>
                    <li><a href="#">注册</a></li>
                </ul>
            </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
    </nav>
    {% endblock %}
    
    {% block content %}
    <div class='container'>
        {% block page_content %}
        默认内容
        {% endblock %}
    </div>
    {% endblock %}
    
  2. base.py

    from flask_bootstrap import Bootstrap
    app = Flask(__name__)
    bootstrap= Bootstrap(app)
    @app.route('/')
    def base():
        return render_template('base.html')
    if __name__ == '__main__':
        manager.run()
    
  3. 渲染效果:

4. 自定义错误页面
  1. 添加视图函数

    @app.errorhandler(404):
    def page_not_found(e):
        return render_template('404.html')
    
  2. 创建模板文件:404.html

    {# 继承自bootstrap的基础模板 #}
    {% extends 'bootstrap.html' %}
    {% block title %}出错了!{% endblock %}
    {% block page_content %}大哥,你是不是搞错了@_@{% endblock %}
    

声明:HEUE NOTE|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA 4.0协议进行授权

转载:转载请注明原文链接 - Flask之最易懂的基础教程