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

 

  

 

posted @ 2018-12-07 23:39  RobotsRising  阅读(440)  评论(0编辑  收藏  举报