zoukankan      html  css  js  c++  java
  • Flask框架:视图

    1、视图中请求request

    1.1、请求request的属性

    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))

      测试代码:

     1 from flask import Flask,request,Response
     2 
     3 app = Flask(import_name=__name__)
     4 
     5 @app.route('/index/')
     6 def index():
     7     print("request.method:",request.method)
     8     print("request.args:",request.args)
     9     print("request.form:",request.form)
    10     print("request.values:",request.values)
    11     print("request.cookies:",request.cookies)
    12     print("request.headers:",request.headers)
    13     print("request.path:",request.path)
    14     print("request.full_path:",request.full_path)
    15     print("request.script_root:",request.script_root)
    16     print("request.url:",request.url)
    17     print("request.base_url:",request.base_url)
    18     print("request.url_root:",request.url_root)
    19     print("request.host_url:",request.host_url)
    20     print("request.files:",request.files)
    21     return Response("index")
    22 
    23 if __name__ == '__main__':
    24     app.run()
    View Code

      使用浏览器访问:http://127.0.0.1:5000/index/?a=1&b=2

      执行结果:

    request.method: GET
    request.args: ImmutableMultiDict([('a', '1'), ('b', '2')])
    request.form: ImmutableMultiDict([])
    request.values: CombinedMultiDict([ImmutableMultiDict([('a', '1'), ('b', '2')]), ImmutableMultiDict([])])
    request.cookies: {'sessionid': 'o3fu279ez1lnsuoung8udxc95sxbglde', 'csrftoken': 'ISStt8sv8ATqEPt0MWfHiy6sqNSmz0GYB35Yam3SyAGcYBRzxnx4rsbr1XeNDF3I'}
    request.headers: Host: 127.0.0.1:5000
    Connection: keep-alive
    Cache-Control: max-age=0
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.9
    Cookie: sessionid=o3fu279ez1lnsuoung8udxc95sxbglde; csrftoken=ISStt8sv8ATqEPt0MWfHiy6sqNSmz0GYB35Yam3SyAGcYBRzxnx4rsbr1XeNDF3I
    
    
    request.path: /index/
    request.full_path: /index/?a=1&b=2
    request.script_root: 
    request.url: http://127.0.0.1:5000/index/?a=1&b=2
    request.base_url: http://127.0.0.1:5000/index/
    request.url_root: http://127.0.0.1:5000/
    request.host_url: http://127.0.0.1:5000/
    request.files: ImmutableMultiDict([])

    1.2、上传文件

      获取文件对象:

    obj = request.files['the_file_name']

      获取安全的文件名:

    secure_filename(f.filename)

      保存文件:

    obj.save('/var/www/uploads/' + secure_filename(f.filename))

      上传文件源码:

     1 import os
     2 import uuid
     3 from flask import Flask,request,Response,redirect,render_template,
     4     url_for
     5 from werkzeug.utils import secure_filename
     6 
     7 UPLOAD_FOLDER = 'upload'
     8 ALLOW_EXTENSIONS = set(['html','htm','doc','docx','mht','pdf','png','jpg'])
     9 app = Flask(__name__)
    10 app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
    11 
    12 #判断文件夹是否存在,如果不存在则创建
    13 if not os.path.exists(UPLOAD_FOLDER):
    14     os.makedirs(UPLOAD_FOLDER)
    15 else:
    16     pass
    17 
    18 # 判断文件后缀是否在列表中
    19 def allowed_file(filename):
    20     return '.' in filename and 
    21            filename.rsplit('.', 1)[1] in ALLOW_EXTENSIONS
    22 
    23 @app.route('/upload/', methods=['GET','POST'])
    24 def upload_file():
    25     if request.method == "GET":
    26         return render_template('index.html')
    27     # 获取post过来的文件名称,从name=file参数中获取
    28     file = request.files['file']
    29     if file and allowed_file(file.filename):
    30         # secure_filename方法会去掉文件名中的中文
    31         filename = secure_filename(file.filename)
    32         # 因为上次的文件可能有重名,因此使用uuid保存文件
    33         file_name = str(uuid.uuid4()) + '.' + filename.rsplit('.', 1)[1]
    34         file_path = os.path.join(app.config['UPLOAD_FOLDER'], file_name)
    35         file.save(file_path)
    36         return redirect(url_for('upload_file', filename=filename))
    37     return Response("上传文件格式不支持,只支持:'html','htm','doc','docx','mht','pdf','png','jpg'")
    38 
    39 if __name__ == '__main__':
    40     app.run()
    app.py

      前端index.html源码:

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6 </head>
     7 <body>
     8 
     9 <form action="" method="post" enctype="multipart/form-data">
    10     <input type="file" name="file">
    11     <input type="submit">
    12 </form>
    13 </body>
    14 </html>
    View Code

    2、响应

      几种响应体:

    return “asdf”
    return jsonify({'k1':'v1'})
    return render_template('xxx.html')
    return redirect('/index/')

      定制响应头:

    obj = make_response("asdf")
    obj.headers['xxxxxxx'] = '123'
    obj.set_cookie('key', 'value')
    return obj

    3、模板语言

      源码:

      后端代码:

     1 from flask import Flask,render_template,request,redirect,session,url_for,jsonify,make_response,Markup,flash,get_flashed_messages
     2 
     3 app = Flask(__name__)
     4 
     5 app.config.from_object("settings.DevelopmentConfig")
     6 
     7 STUDENT_DICT = {
     8     1:{'name':'王龙泰','age':38,'gender':''},
     9     2:{'name':'小东北','age':73,'gender':''},
    10     3:{'name':'田硕','age':84,'gender':''},
    11 }
    12 
    13 
    14 @app.template_global()
    15 def sb(a1, a2):
    16     # {{sb(1,9)}}
    17     return a1 + a2
    18 
    19 @app.template_filter()
    20 def db(a1, a2, a3):
    21     # {{ 1|db(2,3) }}
    22     return a1 + a2 + a3
    23 
    24 
    25 @app.route('/login',methods=["GET","POST"])
    26 def login():
    27     print('login')
    28     if request.method == 'GET':
    29         return render_template('login.html')
    30     user = request.form.get('user')
    31     pwd = request.form.get('pwd')
    32     if user == 'oldboy' and pwd == '666':
    33         session['user'] = user
    34         return redirect('/index')
    35     return render_template('login.html',error='用户名或密码错误')
    36 
    37 
    38 @app.route('/index')
    39 def index():
    40     print('index')
    41     return render_template('index.html',stu_dic=STUDENT_DICT)
    42 
    43 @app.route('/delete/<int:nid>')
    44 def delete(nid):
    45 
    46     del STUDENT_DICT[nid]
    47     return redirect(url_for('index'))
    48 
    49 @app.route('/detail/<int:nid>')
    50 def detail(nid):
    51     info = STUDENT_DICT[nid]
    52     return render_template('detail.html',info=info)
    53 
    54 def func(arg):
    55     return arg + 1
    56 
    57 @app.route('/tpl')
    58 def tpl():
    59     context = {
    60         'users':['longtai','liusong','zhoahuhu'],
    61         'txt':Markup("<input type='text' />"),
    62         'func':func
    63     }
    64 
    65     return render_template('tpl.html',**context)
    66 
    67 if __name__ == '__main__':
    68     app.run()
    app.py
     1 from datetime import timedelta
     2 class Config(object):
     3     DEBUG = False
     4     TESTING = False
     5     SECRET_KEY = "asdfasdfas23"
     6     DATABASE_URI = 'sqlite://:memory:'
     7 
     8     SESSION_COOKIE_NAME = 'session'
     9     SESSION_COOKIE_DOMAIN = None
    10     SESSION_COOKIE_PATH = None
    11     SESSION_COOKIE_HTTPONLY = True
    12     SESSION_COOKIE_SECURE = False
    13     SESSION_REFRESH_EACH_REQUEST = True
    14     PERMANENT_SESSION_LIFETIME = timedelta(hours=1)
    15 
    16 
    17 class ProductionConfig(Config):
    18     DATABASE_URI = 'mysql://user@localhost/foo'
    19 
    20 
    21 class DevelopmentConfig(Config):
    22     DEBUG = True
    23 
    24 
    25 class TestingConfig(Config):
    26     TESTING = True
    settings.py

      前端HTML:

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body>
        <h1>模板</h1>
        {% block content %}{% endblock %}
    </body>
    </html>
    layout.html
    {% extends "layout.html"%}
    
    
    {% block content %}
        {{users.0}}
        {{users[0]}}
        {{txt}}
        <!--{{txt|safe}}-->
        {{func(6)}}
        {{sb(1,9)}}
        {{ 1|db(2,3) }}
        {% if 1|db(2,3) %}
            <div>666</div>
        {% else %}
            <div>999</div>
        {% endif %}
    
        {% include "form.html" %}
    
        {% macro ccccc(name, type='text', value='') %}
            <h1></h1>
            <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
            <input type="submit" value="提交">
        {% endmacro %}
    
        {{ ccccc('n1') }}
    
        {{ ccccc('n2') }}
    
    {% endblock %}
    tpl.html

    4、session

    当请求刚到来:flask读取cookie中session对应的值:eyJrMiI6NDU2LCJ1c2VyIjoib2xkYm95,将该值解密并反序列化成字典,放入内存以便视图函数使用。
    from flask import Flask,render_template,request,redirect,session,url_for,jsonify,make_response,Markup,flash,get_flashed_messages
    
    app = Flask(__name__)
    
    app.config.from_object("settings.DevelopmentConfig")
    
    STUDENT_DICT = {
        1:{'name':'王龙泰','age':38,'gender':'中'},
        2:{'name':'小东北','age':73,'gender':'男'},
        3:{'name':'田硕','age':84,'gender':'男'},
    }
    
     @app.before_request
     def xxxxxx():
         if request.path == '/login':
             return None
         if session.get('user'):
             return None
         return redirect('/login')
    
    @app.route('/login',methods=["GET","POST"])
    def login():
        print('login')
        if request.method == 'GET':
            return render_template('login.html')
        user = request.form.get('user')
        pwd = request.form.get('pwd')
        if user == 'oldboy' and pwd == '666':
            session['user'] = user
            return redirect('/index')
        return render_template('login.html',error='用户名或密码错误')
    
    
    @app.route('/index')
    def index():
        print('index')
        return render_template('index.html',stu_dic=STUDENT_DICT)
    
    @app.route('/delete/<int:nid>')
    def delete(nid):
    
        del STUDENT_DICT[nid]
        return redirect(url_for('index'))
    
    @app.route('/detail/<int:nid>')
    def detail(nid):
        info = STUDENT_DICT[nid]
        return render_template('detail.html',info=info)
    
    
    if __name__ == '__main__':
        app.run()
    View Code

     当请求结束时,flask会读取内存中字典的值,进行序列化+加密,写入到用户cookie中。

    5、闪现flash

      原理:在session中存储一个数据,读取时通过pop将数据移除。

     1 from flask import Flask,flash,get_flashed_messages
     2 
     3 app = Flask(__name__)
     4 app.secret_key = "123213132"
     5 
     6 @app.route('/page1')
     7 def page1():
     8 
     9     flash('临时数据存储','error')
    10     flash('sdfsdf234234','error')
    11     flash('adasdfasdf','info')
    12 
    13     return "Session"
    14 
    15 @app.route('/page2')
    16 def page2():
    17     print(get_flashed_messages(category_filter=['error']))
    18     return "Session"
    19 
    20 
    21 if __name__ == '__main__':
    22     app.run()
    View Code

    6、中间件

      app.run()执行Flask类的run方法,该方法调用werkzeug.serving的run_simple方法:

    from werkzeug.serving import run_simple
    
    try:
        run_simple(host, port, self, **options)
    finally:
        # reset the first request information if the development server
        # reset normally.  This makes it possible to restart the server
        # without reloader and that stuff from an interactive shell.
        self._got_first_request = False

      其中self即是Flask类实例化的对象app。

      用户请求到来后会执行self方法,即app()。app()会调用app对象的__call__方法。

    def __call__(self, environ, start_response):
        """The WSGI server calls the Flask application object as the
        WSGI application. This calls :meth:`wsgi_app` which can be
        wrapped to applying middleware."""
        return self.wsgi_app(environ, start_response)

      __call__方法中调用app对象的wsgi_app方法。

      因此如果要实现中间件功能,就必须在wsgi_app方法执行前后添加功能。即在wsgi_app的__call__方法中添加请求处理前功能和请求处理后功能。

     1 from flask import Flask
     2 
     3 app = Flask(__name__)
     4 
     5 @app.route('/index')
     6 def index():
     7     print('index')
     8     return "Index"
     9 
    10 class Middleware(object):
    11     def __init__(self,old):
    12         self.old = old
    13 
    14     def __call__(self, *args, **kwargs):
    15         print("")
    16         ret = self.old(*args, **kwargs)
    17         print("")
    18         return ret
    19 
    20 if __name__ == '__main__':
    21     app.wsgi_app = Middleware(app.wsgi_app)
    22     app.run()

    7、特殊装饰器

      before_request:请求处理前执行

      after_request:请求处理完后执行

      before_first_request:第一次请求处理前执行

      template_global:模板中使用

      template_filter:模板中用于过滤

      errorhandler:请求发生错误时执行

     1 from flask import Flask
     2 app = Flask(__name__)
     3 
     4 @app.before_first_request
     5 def x1():
     6     print('123123')
     7 
     8 @app.route('/index')
     9 def index():
    10     print('index')
    11     return "Index"
    12 
    13 @app.route('/order')
    14 def order():
    15     print('order')
    16     return "order"
    17 
    18 @app.errorhandler(404)
    19 def not_found(arg):
    20     print(arg)
    21     return "没找到"
    22 
    23 if __name__ == '__main__':
    24     app.run()
    View Code

     8、CBV

     1 import functools
     2 from flask import Flask,views,Response
     3 
     4 app = Flask(__name__)
     5 
     6 def wrapper(func):
     7     @functools.wraps(func)
     8     def inner(*args,**kwargs):
     9         return func(*args,**kwargs)
    10     return inner
    11 
    12 class UserView(views.MethodView):
    13     methods = ['GET','POST']
    14     decorators = [wrapper,]
    15 
    16     def get(self,*args,**kwargs):
    17         return 'GET'
    18 
    19     def post(self,*args,**kwargs):
    20         return 'POST'
    21 
    22 app.add_url_rule('/user',None,UserView.as_view('uuuu'))
    23 
    24 if __name__ == '__main__':
    25     app.run()
    View Code

     9、蓝图Blueprint

      项目目录:

        crm:

          crm:

            static

            templates:

              login.html

            views:

              account.py

              user.py

            __init__.py

           manage.py

     1 <!DOCTYPE html>
     2 <html lang="zh-CN">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6     <meta name="viewport" content="width=device-width, initial-scale=1">
     7 </head>
     8 <body>
     9     <h1>用户登录</h1>
    10 </body>
    11 </html>
    login.html
     1 from flask import Blueprint,render_template
     2 
     3 ac = Blueprint('ac',__name__)
     4 
     5 @ac.before_request
     6 def x1():
     7     print('app.before_request')
     8 
     9 @ac.route('/login')
    10 def login():
    11     return render_template('login.html')
    12 
    13 @ac.route('/logout')
    14 def logout():
    15     return 'Logout'
    account.py
     1 from flask import Blueprint
     2 
     3 uc = Blueprint('uc',__name__)
     4 
     5 @uc.route('/list')
     6 def list():
     7     return 'List'
     8 
     9 @uc.route('/detail')
    10 def detail():
    11     return 'detail'
    user.py
     1 from flask import Flask
     2 from .views.account import ac
     3 from .views.user import uc
     4 
     5 def create_app():
     6 
     7     app = Flask(__name__)
     8 
     9     # @app.before_request
    10     # def x1():
    11     #     print('app.before_request')
    12     app.register_blueprint(ac)
    13     app.register_blueprint(uc,url_prefix='/api')
    14     return app
    __init__.py
    1 from crm import create_app
    2 
    3 app = create_app()
    4 
    5 if __name__ == '__main__':
    6     app.run()
    manage.py

      

  • 相关阅读:
    ORACLE之常用FAQ V1.0二(构架系统) (1)
    如何快速杀去世占用过多本钱(CPU,内存)的数据库历程
    Eclipse快捷键大全
    (收藏)STL MAP 详解
    怎么在安装目录下创建一个文件
    MFC自绘属性的总结
    文件夹总结
    公元纪年转换为干支纪年
    重载运算符operator
    VS2005快捷键大全
  • 原文地址:https://www.cnblogs.com/bad-robot/p/10085861.html
Copyright © 2011-2022 走看看