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

      

  • 相关阅读:
    ZOJ 3332 Strange Country II
    ZOJ 3331 Process the Tasks(双塔DP)
    ZOJ 3326 An Awful Problem(模拟)
    HDU 1796 How many integers can you find(容斥原理)
    HDU 4059 The Boss on Mars(容斥原理)
    HDU 4135 Co-prime(容斥原理)
    HDU 5677 ztr loves substring(回文串加多重背包)
    CodeForces 668B Little Artem and Dance
    CodeForces 667A Pouring Rain
    Java实现 LeetCode 764 最大加号标志(暴力递推)
  • 原文地址:https://www.cnblogs.com/bad-robot/p/10085861.html
Copyright © 2011-2022 走看看