flask基础

一.flask是什么?

  Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。

  因为它使用简单的核心,用 extension 增加其他功能。Flask没有默认使用的数据库、窗体验证工具。

二.知识点

  1.实例化flask对象

app = Flask(__name__,template_folder='templates',static_url_path='/static')

    2.添加路由的方式

方式一:
  @app.route('/login')  
  def index():
     return render_template('login.html')

方式二:
  def login():
     return render_template('login.html')
  app.add_url_rule('/login', "n1", login)  #'n1'为别名

  3.添加路由关系

    将url和视图函数封装成一个Rule对象)添加到Flask的url_map字段中(详见)

  4.flask+自定义装饰器(简单登录验证)

 1 from flask import Flask,render_template,request,redirect,session
 2 app = Flask(__name__,template_folder='templates',static_url_path='/static')
 3 app.secret_key = "asdfafsd"  #加盐作用,必须有值
 4 
 5 @app.route('/login',methods=['GET','POST'])
 6 def login():
 7     if request.method == 'GET':
 8         return render_template('login.html')
 9     else:
10         user = request.form.get('user')
11         pwd = request.form.get('pwd')
12         if user == '张良' and pwd == '123':
13             session['user_info'] = user
14             return redirect('/index')
15         else:
16             return render_template('login.html',msg='用户名或者密码错误!')
17 
18 def deco(func):
19     def _deco(*args,**kwargs):
20         if not session.get('user_info'):
21             return redirect('/login')
22         return func(*args, **kwargs)
23     return _deco
24 
25 @app.route('/index',methods=['GET']) 
26 @deco  #调用装饰器函数写在路由下面
27 def index():
28     return render_template('index.html')
29 
30 if __name__ == '__main__':
31     app.run()
32 
33 login.html
34 <body>
35     <form method="post">
36         <p>用户名<input type="text" name="user"></p>
37         <p>密  码<input type="text" name="pwd"></p>
38         <input type="submit">{{ msg }}
39     </form>
40 </body>
View Code

  5.请求响应相关

1 request.form   #POST请求,获取表单内容
2 request.args   #GET请求,字典形式的,获取url中传过来的键值对
3 request.querystring  #GET请求,bytes形式的    
4 request.url #返回当前请求完整的URL
5 request.base_url #不带参数的URL
6 request.path #url中的路径部分
from urllib.parse import urlencode,quote,unquote,make_response
get_data = request.args  #ImmutableMultiDict([''id':'1','name':'tom'])
get_dict = get_data.to_dict  #{''id':'1','name':'tom'}
get_dict['xx] = 18
url = urlencode(get_dict)  #id=1&name=tom&xx=18

request.files
obj = request.files['the_file_name']
obj.save('/var/www/uploads/' + secure_filename(f.filename))

#请求文件中的url中如果有中文,会得到:
    val = "%E6%8A%8A%E5%87%A0%E4%B8%AA"
    解码:
    unquote(val)

    #返回更多的内容

    response = make_response("xxxx")
    
    response.header['xxx'] = ‘123return response

  5.路由系统

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

常用路由系统有以上五种,所有的路由系统都是基于一下对应关系来处理:

DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,
    'path':             PathConverter,
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,
}
@app.route和app.add_url_rule参数:
 1 rule,                       URL规则
 2             view_func,                  视图函数名称
 3             defaults=None,              默认值,当URL中无参数,函数需要参数时,使用defaults={'k':'v'}为函数提供参数
 4             endpoint=None,              名称,用于反向生成URL,即: url_for('名称')
 5             methods=None,               允许的请求方式,如:["GET","POST"]
 6             
 7 
 8             strict_slashes=None,        对URL最后的 / 符号是否严格要求,
 9                                         如:
10                                             @app.route('/index',strict_slashes=False),
11                                                 访问 http://www.xx.com/index/ 或 http://www.xx.com/index均可
12                                             @app.route('/index',strict_slashes=True)
13                                                 仅访问 http://www.xx.com/index 
14             redirect_to=None,           重定向到指定地址
15                                         如:
16                                             @app.route('/index/<int:nid>', redirect_to='/home/<nid>')
17 18                                             def func(adapter, nid):
19                                                 return "/home/888"
20                                             @app.route('/index/<int:nid>', redirect_to=func)
21             subdomain=None,             子域名访问
22                                                 from flask import Flask, views, url_for
23 
24                                                 app = Flask(import_name=__name__)
25                                                 app.config['SERVER_NAME'] = 'wupeiqi.com:5000'
26 
27 
28                                                 @app.route("/", subdomain="admin")
29                                                 def static_index():
30                                                     """Flask supports static subdomains
31                                                     This is available at static.your-domain.tld"""
32                                                     return "static.your-domain.tld"
33 
34 
35                                                 @app.route("/dynamic", subdomain="<username>")
36                                                 def username_index(username):
37                                                     """Dynamic subdomains are also supported
38                                                     Try going to user1.your-domain.tld/dynamic"""
39                                                     return username + ".your-domain.tld"
40 
41 
42                                                 if __name__ == '__main__':
43                                                     app.run()
View Code

  URL反向解析

from flask import Flask, url_for
def index():
    v = url_for("xxx")
    print(v)
    return "index"

@app.route('/zzz/<int:nid>',endpoint="aaa")  #endpoint是别名
def zzz(nid):
    v = url_for("aaa",nid=nid)
    print(v)
    return "index2"
redirect_to:直接重定向,原url有参数时,跳转时也要传参,注意:不用加类型

6.自定制正则路由匹配
 1 from flask import Flask, views, url_for
 2             from werkzeug.routing import BaseConverter
 3 
 4             app = Flask(import_name=__name__)
 5 
 6 
 7             class RegexConverter(BaseConverter):
 8                 """
 9                 自定义URL匹配正则表达式
10                 """
11                 def __init__(self, map, regex):
12                     super(RegexConverter, self).__init__(map)
13                     self.regex = regex
14 
15                 def to_python(self, value):
16                     """
17                     路由匹配时,匹配成功后传递给视图函数中参数的值
18                     :param value: 
19                     :return: 
20                     """
21                     return int(value)
22 
23                 def to_url(self, value):
24                     """
25                     使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
26                     :param value: 
27                     :return: 
28                     """
29                     val = super(RegexConverter, self).to_url(value)
30                     return val
31 
32             # 添加到flask中
33             app.url_map.converters['regex'] = RegexConverter
34 
35 
36             @app.route('/index/<regex("\d+"):nid>')
37             def index(nid):
38                 print(url_for('index', nid='888'))
39                 return 'Index'
40 
41 
42             if __name__ == '__main__':
43                 app.run()
44 
45 #自定制正则路由匹配

  7.模板使用

  和Django使用类似......

  不同之处:

     前端循环字典时,dict.items(),后面的括号需要加;后端传来一个字典,前端可用get.('xxx')取值

  markup:相当于Django的mark_safe;

  template_global() template_filter() (在所有的页面都可以使用)

1 @app.template_global()
2 def dd(a1, a2):
3     return a1 + a2
4 @app.template_filter()
5 def pp(a1, a2, a3):
6     return a1 + a2 + a3
7 
8 调用:{{dd(1,2)}}  {{ 1|pp(2,3)}}(用‘|’区分)
View Code

  宏:只有定义的东西在很多地方去使用的时候才去用它

1 {% macro input(name, type='text', value=' ') %}
2     <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
3 {% endmacro %}
4 
5 {{ input('n1') }} 
View Code

  8.session

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

  • 删除:session.pop('username', None)
 1 from flask import Flask, session, redirect, url_for, escape, request
 2  
 3 app = Flask(__name__)
 4  
 5 @app.route('/')
 6 def index():
 7     if 'username' in session:
 8         return 'Logged in as %s' % escape(session['username'])
 9     return 'You are not logged in'
10  
11 @app.route('/login', methods=['GET', 'POST'])
12 def login():
13     if request.method == 'POST':
14         session['username'] = request.form['username']
15         return redirect(url_for('index'))
16     return '''
17         <form action="" method="post">
18             <p><input type=text name=username>
19             <p><input type=submit value=Login>
20         </form>
21     '''
22  
23 @app.route('/logout')
24 def logout():
25     # remove the username from the session if it's there
26     session.pop('username', None)
27     return redirect(url_for('index'))
28  
29 # set the secret key.  keep this really secret:
30 app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
31 
32 基本使用
View Code
pip3 install Flask-Session
        
        run.py
            from flask import Flask
            from flask import session
            from pro_flask.utils.session import MySessionInterface
            app = Flask(__name__)

            app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
            app.session_interface = MySessionInterface()

            @app.route('/login.html', methods=['GET', "POST"])
            def login():
                print(session)
                session['user1'] = 'alex'
                session['user2'] = 'alex'
                del session['user2']

                return "内容"

            if __name__ == '__main__':
                app.run()

        session.py
            #!/usr/bin/env python
            # -*- coding:utf-8 -*-
            import uuid
            import json
            from flask.sessions import SessionInterface
            from flask.sessions import SessionMixin
            from itsdangerous import Signer, BadSignature, want_bytes


            class MySession(dict, SessionMixin):
                def __init__(self, initial=None, sid=None):
                    self.sid = sid
                    self.initial = initial
                    super(MySession, self).__init__(initial or ())


                def __setitem__(self, key, value):
                    super(MySession, self).__setitem__(key, value)

                def __getitem__(self, item):
                    return super(MySession, self).__getitem__(item)

                def __delitem__(self, key):
                    super(MySession, self).__delitem__(key)



            class MySessionInterface(SessionInterface):
                session_class = MySession
                container = {}

                def __init__(self):
                    import redis
                    self.redis = redis.Redis()

                def _generate_sid(self):
                    return str(uuid.uuid4())

                def _get_signer(self, app):
                    if not app.secret_key:
                        return None
                    return Signer(app.secret_key, salt='flask-session',
                                  key_derivation='hmac')

                def open_session(self, app, request):
                    """
                    程序刚启动时执行,需要返回一个session对象
                    """
                    sid = request.cookies.get(app.session_cookie_name)
                    if not sid:
                        sid = self._generate_sid()
                        return self.session_class(sid=sid)

                    signer = self._get_signer(app)
                    try:
                        sid_as_bytes = signer.unsign(sid)
                        sid = sid_as_bytes.decode()
                    except BadSignature:
                        sid = self._generate_sid()
                        return self.session_class(sid=sid)

                    # session保存在redis中
                    # val = self.redis.get(sid)
                    # session保存在内存中
                    val = self.container.get(sid)

                    if val is not None:
                        try:
                            data = json.loads(val)
                            return self.session_class(data, sid=sid)
                        except:
                            return self.session_class(sid=sid)
                    return self.session_class(sid=sid)

                def save_session(self, app, session, response):
                    """
                    程序结束前执行,可以保存session中所有的值
                    如:
                        保存到resit
                        写入到用户cookie
                    """
                    domain = self.get_cookie_domain(app)
                    path = self.get_cookie_path(app)
                    httponly = self.get_cookie_httponly(app)
                    secure = self.get_cookie_secure(app)
                    expires = self.get_expiration_time(app, session)

                    val = json.dumps(dict(session))

                    # session保存在redis中
                    # self.redis.setex(name=session.sid, value=val, time=app.permanent_session_lifetime)
                    # session保存在内存中
                    self.container.setdefault(session.sid, val)

                    session_id = self._get_signer(app).sign(want_bytes(session.sid))

                    response.set_cookie(app.session_cookie_name, session_id,
                                        expires=expires, httponly=httponly,
                                        domain=domain, path=path, secure=secure)

自定义Session
自定义session
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
pip3 install redis
pip3 install flask-session

"""


from flask import Flask, session, redirect
from flask.ext.session import Session


app = Flask(__name__)
app.debug = True
app.secret_key = 'asdfasdfasd'


app.config['SESSION_TYPE'] = 'redis'
from redis import Redis
app.config['SESSION_REDIS'] = Redis(host='192.168.0.94',port='6379')
Session(app)


@app.route('/login')
def login():
    session['username'] = 'alex'
    return redirect('/index')


@app.route('/index')
def index():
    name = session['username']
    return name


if __name__ == '__main__':
    app.run()

第三方session
第三方session

  session配置参数

- session超时时间如何设置?
            app.config['SESSION_COOKIE_NAME'] = 'session_lvning'
            跟session相关的配置文件
            """
            '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)

   9.闪现

  本质:flash是基于session创建的,flash支持往里边放值,只要你取一下就没有了,相当于pop了一下。

 1 from flask import Flask, flash, redirect, render_template, request, get_flashed_messages
 2 app = Flask(__name__)
 3 app.secret_key = 'some_secret'
 4 flag = True
 5 @app.route('/index')
 6 def index1():
 7     global flag
 8     if flag:
 9         flash('登录成功!')
10         flag=False
11     return render_template('index.html')
12 
13 if __name__ == "__main__":
14     app.run(port=8600)
15 
16 #index.html
17 <!DOCTYPE html>
18 <html lang="en">
19 <head>
20     <meta charset="UTF-8">
21     <title>Title</title>
22 </head>
23 <body>
24 {% for msg in get_flashed_messages() %}
25     <p>{{ msg }}</p>
26 {% endfor %}
27 </body>
28 </html>
代码实例

  10.flask中通过内置函数实现中间价的效果

from flask import Flask,session,Session,flash,get_flashed_messages,redirect,render_template,request
app = Flask(__name__)
app.secret_key ='sdfsdfsdf'

@app.before_request
def process_request1():
    print('process_request1')

@app.after_request
def process_response1(response):
    print('process_response1')
    return response

@app.before_request
def process_request2():
    print('process_request2')

@app.after_request
def process_response2(response):   #参数也得有
    print('process_response2')
    return response   #必须有返回值
#注:@app.before_first_request:当程序运行起来,第一个请求来的时候就只执行一次,下次再来就不会在执行了

  11.flask中的CBV模式和FBV模式

 1 def auth(func):
 2             def inner(*args, **kwargs):
 3                 result = func(*args, **kwargs)
 4                 return result
 5             return inner
 6 
 7         class IndexView(views.MethodView):
 8             # methods = ['POST']  #只允许POST请求访问
 9             decorators = [auth,]  #如果想给所有的get,post请求加装饰器,就可以这样来写
10   
11             def get(self):   #如果是get请求需要执行的代码
12                 v = url_for('index')
13                 print(v)
14                 return "GET"
15 
16             def post(self):  #如果是post请求执行的代码
17                 return "POST"
18 
19         app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  #name指定的是别名,会当做endpoint使用
20 
21         if __name__ == '__main__':
22             app.run()
CBV模式
 1 方式一:
 2     @app.route('/index',endpoint='xx')
 3     def index(nid):
 4         url_for('xx',nid=123)
 5         return "Index"
 6 
 7     方式二:
 8     def index(nid):
 9         url_for('xx',nid=123)
10         return "Index"
11 
12     app.add_url_rule('/index',index)
FBV模式

 

 

 

 
posted @ 2018-01-06 15:11  爱笑的大象  阅读(370)  评论(0编辑  收藏  举报