• Python之flask总结


    一、flask

         a、Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器

         b、“微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此,Flask 可以与您珠联璧合。

         c、默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用。

    二、安装

          a、安装:pip3 install flask

    三、虚拟环境

          a、安装: pip3 install virtualenv

          b、# 创建虚拟环境 virtualenv env1

          c、# 进入虚拟环境 Scripts/activate

          d、 # 退出虚拟环境 Scripts/deactivate

    四、flask框架

          a、简介:轻量级框架
                         Django:无socket、中间件、路由系统、视图(CBV,FBV)、 模板、ORM、cookie、Session、Admin、Form、缓存、信号、序列化....
                         Flask:无socket、中间件(扩展)、路由系统、视图(CBV)、第三方模板(jinja2)、cookie、Session弱爆了

          b、 什么是wsgi?
                               Web服务网管接口,协议。

          c、Flask依赖一个实现了WSGI协议的模块:werkzeug

    五、flask

           a、 -依赖于wsgi模块:wsgiref,werkzeug,wsgi

           b、  -实例化Flask对象

                      -静态文件前缀  /xxx

                      -静态文件目录

                      -模板路径

            c、 添加路由关系      

                      -将 Rule(url和视图函数)添加到Flask对象的url_map字段中

                      -两种添加路由的方式

            d、request

                     -request.form

                     -request.args 

    六、基本使用

    from flask import Flask
    
    # 实例化Flask对象
    app = Flask(__name__)
    
    # 生成路由关系,并把关系保存到某个地方,app对象的 url_map字段中
    @app.route('/xxxx')  # @decorator
    def index():
        return "Index"
    
    # def index():
    #     return "Index"
    # app.add_url_rule('/xxx', "n1", index)
    
    if __name__ == '__main__':
        # 启动程序,监听用户请求
        # 一旦请求到来,执行 app.__call__方法
        # 封装用户请求
        # 进行路由匹配
        app.run()

         a、保存session的数据存到了浏览器上,
            - 优点:减轻了服务端的压力
            - 缺点:不安全

         b、路由系统:  

    • @app.route('/post/<path:path>')
    • @app.route('/login', methods=['GET', 'POST'])
    • @app.route('/user/<username>')
    • @app.route('/post/<int:post_id>')
    • @app.route('/post/<float:post_id>')

    七、路由系统

         a、  -可传入参数     

                @app.route('/user/<username>')

                @qpp.route('/post/<int:post_id>',methods=['GET','POST'],endpoint='fff')

         b、反向生成URL:url_for

         c、扩展Flask的路由系统,让它支持正则:

    from flask import Flask,url_for
    
                    app = Flask(__name__)
    
                    # 定义转换的类
                    from werkzeug.routing import BaseConverter
                    class RegexConverter(BaseConverter):
                        """
                        自定义URL匹配正则表达式
                        """
    
                        def __init__(self, map, regex):
                            super(RegexConverter, self).__init__(map)
                            self.regex = regex
    
                        def to_python(self, value):
                            """
                            路由匹配时,匹配成功后传递给视图函数中参数的值
                            :param value: 
                            :return: 
                            """
                            return int(value)
    
                        def to_url(self, value):
                            """
                            使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
                            :param value: 
                            :return: 
                            """
                            val = super(RegexConverter, self).to_url(value)
                            return val
    
                    # 添加到converts中
                    app.url_map.converters['xxx'] = RegexConverter
    
                    # 进行使用
                    @app.route('/index/<xxx("d+"):nid>',endpoint='xx')
                    def index(nid):
                        url_for('xx',nid=123)
                        return "Index"
    
                    if __name__ == '__main__':
                        app.run()

    八、请求响应

    from flask import Flask
        from flask import request
        from flask import render_template
        from flask import redirect
        from flask import make_response
    
        app = Flask(__name__)
    
    
        @app.route('/login.html', methods=['GET', "POST"])
        def login():
    
            # 请求相关信息
            # request.method
            # request.args
            # request.form
            # request.values
            # request.cookies
            # request.headers
            # request.path
            # request.full_path
            # request.script_root
            # request.url
            # request.base_url
            # request.url_root
            # request.host_url
            # request.host
            # request.files
            # obj = request.files['the_file_name']
            # obj.save('/var/www/uploads/' + secure_filename(f.filename))
    
            # 响应相关信息
            # return "字符串"
            # return render_template('html模板路径',**{})
            # return redirect('/index.html')
    
            # response = make_response(render_template('index.html'))
            # response是flask.wrappers.Response类型
            # response.delete_cookie('key')
            # response.set_cookie('key', 'value')
            # response.headers['X-Something'] = 'A value'
            # return response
    
    
            return "内容"
    
        if __name__ == '__main__':
            app.run()

        a、在django中用make_safe而在Flask中用make_response

    九、模板语言   

         a、模板的使用

                   Flask使用的是Jinja2模板,所以其语法和Django无差别

         b、自定义模板方法

                   Flask中自定义模板方法的方式和Bottle相似,创建一个函数并通过参数的形式传入render_template,

    十、session 

          a、 -session是否还有其他方法?

                         -它与字典方法相同

          b、  -session超时时间如何设置:

    app.config['SESSION_COOKIE_NAME'] = 'session_lvning'
                """
                'SESSION_COOKIE_NAME':                  'session',
                'SESSION_COOKIE_DOMAIN':                None,
                'SESSION_COOKIE_PATH':                  None,
                'SESSION_COOKIE_HTTPONLY':              True,
                'SESSION_COOKIE_SECURE':                False,
                'SESSION_REFRESH_EACH_REQUEST':         True,
                'PERMANENT_SESSION_LIFETIME':           timedelta(days=31)

         c、除请求对象之外,还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名要使用会话,你需要设置一个密钥。

         d、

    • 设置:session['username'] = 'xxx'

    • 删除:session.pop('username', None)

    十一、闪现(flash)

         a、session从在在服务端的一个字典中,session保存的数据取一次,它还是会有。而flash是基于session创建的,flash支持在里面放值,只要在里面取值它就会没有。闪现就是

         b、在session的基础上,把它的值真实的放在session上,当去它的时候不仅把它的值取走,还把session的东西去掉。

    十二、蓝图

         a、蓝图用于为应用提供目录划分

      • 蓝图URL前缀:xxx = Blueprint('account', __name__,url_prefix='/xxx')
      • 蓝图子域名:xxx = Blueprint('account', __name__,subdomain='admin')
        # 前提需要给配置SERVER_NAME: app.config['SERVER_NAME'] = 'wupeiqi.com:5000'
        # 访问时:admin.wupeiqi.com:5000/login.html

    十三、DBUtils

          a、DBUtils是Python的一个用于实现数据库连接池的模块。

          b、连接池的三种模式:

                (1)、第一种模式:

                                     它的缺点:每一次请求反复创建数据库的链接,链接的次数太多

                 (2)、第二种模式:

                                     它的缺点:不能支持并发

                  (3)、第三种模式:

                                    它是基于DBUtils实现数据库连接池

                                            -为每个线程创建一个链接,该线程关闭时,不是真正的关闭,本线程再次调用时,还是使用的最开始的创建的链接,知道线程终止,数据库链接才关闭

                                           -创建一个连接池(10个链接),为所有线程提供链接,使用时来进行获取,使用完毕时,再次放回到连接池。

           c、DBUtils的应用:

    import time
    import pymysql
    import threading
    from DBUtils.PooledDB import PooledDB, SharedDBConnection
    POOL = PooledDB(
        creator=pymysql,  # 使用链接数据库的模块
        maxconnections=6,  # 连接池允许的最大连接数,0和None表示不限制连接数
        mincached=2,  # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
        maxcached=5,  # 链接池中最多闲置的链接,0和None不限制
        maxshared=3,  # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。
        blocking=True,  # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
        maxusage=None,  # 一个链接最多被重复使用的次数,None表示无限制
        setsession=[],  # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]
        ping=0,
        # ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always
        host='127.0.0.1',
        port=3306,
        user='root',
        password='123',
        database='pooldb',
        charset='utf8'
    )

    十四、session

          a、 session和cookie的原理和区别:

                   cookie是保存在浏览器上的键值对
                   session是存在服务端的键值对(服务端的session就是一个大字典,字典中是随机字符串)(session与request原理相同)(session原理跟上下文也有关系)

                   session依赖于cookie存在

          b、  session流程      

    当请求第一次进来,生成随机字符串
                      -发给用户cookie
                      -保存到session字典中时
                      它调用stark将随机字符串和对应的值放到local
                    视图函数
                     -使用时导入用top(它拿的是session)
                         session=LocalProxy(partile(_lookup_req_object,'session '))
                   请求处理完毕:
                         内存处理完毕后,将session做持久化(session存到数据库,存到Redis,存到加密的cookie中)

    十五、session源码解析

         a、先执行Flask的__call__方法 ,调用出来wsgi_app,它先做request的上下文做完,请求刚进来到push中,它先处理request将请求相关的数据,然后添加到了local中,

         b、 紧接着处理session(将RequestContext对象(request,session)添加到local中),request(将request信息封装到Request(environ)对象并复制给requestContext 对                       象),然后获取cookie中的随机字符串,检验是否有,没有就生成。根据随机字符串,获取服务端session保存的值。把session放到内存中,

         c、  执行wsgi_app方法下面的视图函数。执行完视图函数返回到full_dispatch_requesthong ,触发只执行一次的装饰器中(触发Flask信号),

         d、  执行完这个装饰器,紧接着执行下面的特殊的装饰器,如果这些特殊装饰器没有返回值,那么rv=None,如果有返回值,页面时就显示这个返回值,

         e、如果没有返回值,触发执行那个视图函数,拿返回值。请求执行完返回后,调用finalize_request,对它的返回值进行封装。

    十六、Flask和Django的区别 

         a、请求相关的数据           

                      -Django:参数

                      -Flask:    基于Local,LocalStark对象

         b、 多个请求进来会不会混淆            

                      -单线程

                      -多线程

                      -协程

                        解决: from greenlet import getcurrent as get_ident

    十七、Flask信号

        a、 Flask框架中的信号基于blinker

        b、安装: pip3 install blinker

        c、十个信号

    1. 内置信号
                10个信号:
                    2. request_started = _signals.signal('request-started')                # 请求到来前执行
                    5. request_finished = _signals.signal('request-finished')              # 请求结束后执行
                     
                    3. before_render_template = _signals.signal('before-render-template')  # 模板渲染前执行
                    4. template_rendered = _signals.signal('template-rendered')            # 模板渲染后执行
                     
                    2/3/4/5或不执行 got_request_exception = _signals.signal('got-request-exception')    # 请求执行出现异常时执行
                     
                    6. request_tearing_down = _signals.signal('request-tearing-down')      # 请求执行完毕后自动执行(无论成功与否)
                    7. appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 请求上下文执行完毕后自动执行(无论成功与否)
                     
                     
                    1. appcontext_pushed = _signals.signal('appcontext-pushed')            # 请求app上下文push时执行
                    
                    8. appcontext_popped = _signals.signal('appcontext-popped')            # 请求上下文pop时执行
                    
                    message_flashed = _signals.signal('message-flashed')                   # 调用flask在其中添加数据时,自动触发

         d、flask信号本生自己没有,用的是别人的,并且这些信号通过装饰器全部可以代替了的,但是Django里面有些特殊的
    就是那些model操作根本没有装饰器,就是同过内置的信号来完成的

    十八、django内置的信号

    Request/response signals
                        request_started             # 请求到来前,自动触发
                        request_finished            # 请求结束后,自动触发
                        got_request_exception       # 请求异常后,自动触发
                    
                    Model signals
                        pre_init                    # django的modal执行其构造方法前,自动触发
                        post_init                   # django的modal执行其构造方法后,自动触发
                        
                        pre_save                    # django的modal对象保存前,自动触发
                        post_save                   # django的modal对象保存后,自动触发
                        
                        pre_delete                  # django的modal对象删除前,自动触发
                        post_delete                 # django的modal对象删除后,自动触发
                        
                        m2m_changed                 # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
                        
                        class_prepared              # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
                        
                    Management signals
                        pre_migrate                 # 执行migrate命令前,自动触发
                        post_migrate                # 执行migrate命令后,自动触发
                    
                    Test signals
                        setting_changed             # 使用test测试修改配置文件时,自动触发
                        template_rendered           # 使用test测试渲染模板时,自动触发
                    Database Wrappers
                        connection_created          # 创建数据库连接时,自动触发

    十九、Wtform

        a、WTForms是一个支持多个web框架的form组件,主要用于对用户请求数据进行验证。

        b、安装: pip3 install wtform

        c、用途:

           1、用户登录注册

                   当用户登录时候,需要对用户提交的用户名和密码进行多种格式校验。如:

                  用户不能为空;用户长度必须大于6;

                  密码不能为空;密码长度必须大于12;密码必须包含 字母、数字、特殊字符等(自定义正则);

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask import Flask, render_template, request, redirect
    from wtforms import Form
    from wtforms.fields import core
    from wtforms.fields import html5
    from wtforms.fields import simple
    from wtforms import validators
    from wtforms import widgets
    
    app = Flask(__name__, template_folder='templates')
    app.debug = True
    
    
    class LoginForm(Form):
        name = simple.StringField(
            label='用户名',
            validators=[
                validators.DataRequired(message='用户名不能为空.'),
                validators.Length(min=6, max=18, message='用户名长度必须大于%(min)d且小于%(max)d')
            ],
            widget=widgets.TextInput(),
            render_kw={'class': 'form-control'}
    
        )
        pwd = simple.PasswordField(
            label='密码',
            validators=[
                validators.DataRequired(message='密码不能为空.'),
                validators.Length(min=8, message='用户名长度必须大于%(min)d'),
                validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*d)(?=.*[$@$!%*?&])[A-Za-zd$@$!%*?&]{8,}",
                                  message='密码至少8个字符,至少1个大写字母,1个小写字母,1个数字和1个特殊字符')
    
            ],
            widget=widgets.PasswordInput(),
            render_kw={'class': 'form-control'}
        )
    
    
    
    @app.route('/login', methods=['GET', 'POST'])
    def login():
        if request.method == 'GET':
            form = LoginForm()
            return render_template('login.html', form=form)
        else:
            form = LoginForm(formdata=request.form)
            if form.validate():
                print('用户提交数据通过格式验证,提交的值为:', form.data)
            else:
                print(form.errors)
            return render_template('login.html', form=form)
    
    if __name__ == '__main__':
        app.run()
    app.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>登录</h1>
    <form method="post">
        <!--<input type="text" name="name">-->
        <p>{{form.name.label}} {{form.name}} {{form.name.errors[0] }}</p>
    
        <!--<input type="password" name="pwd">-->
        <p>{{form.pwd.label}} {{form.pwd}} {{form.pwd.errors[0] }}</p>
        <input type="submit" value="提交">
    </form>
    </body>
    </html>
    login

    二十、SQLALchemy

        a、介绍 :      

               SQLALchemy是一个基于Python实现的ORM框架。该框架是建立在DB API之上,使用关系对象映射进行数据库操作

               简言之便就是:将类和对象转换成SQL,然后使用数据API执行SQL并获取执行的结果

        b、安装: pip3 install SQLALchemy

        c、组成部分

     engine,                                     框架的引擎
    
         Connection  Pooling  ,                      数据库连接池
    
         Dialect,                                    选择链接数据库的DB  API种类
    
         Schema /Types,                              架构和类型     
    
         SQL Exprression Language,                   SQL表达式语言

        d、SQLALcheam本省无法操作数据库,其必须来pymysql等第三方插件, Dialect用于数据API的交流,根据配置文件的不同

    调用不同的数据库API,从而实现对数据库的操作

    MySQL-Python
        mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
        
    pymysql
        mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
        
    MySQL-Connector
        mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>
        
    cx_Oracle
        oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]
        
    更多:http://docs.sqlalchemy.org/en/latest/dialects/index.html

      

  • 相关阅读:
    java 网络编程
    JAVA 中for-each循环使用方法
    JAVA 常用集合接口List、Set、Map总结
    android学习计划
    ExtJs
    jQuery easyui
    MVC
    简易servlet计算器
    使用servlet实现用户注册功能
    用JavaBean实现数据库的连接和关闭,在jsp页面输出数据库中student表中学生的信息
  • 原文地址:https://www.cnblogs.com/mengqingjian/p/8452898.html
Copyright © 2020-2023  润新知