flask笔记

一 | 基本使用

from flask import Flask 

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

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

二 | 配置文件

1. 默认值

flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为:

{
        'DEBUG':                                get_debug_flag(default=False),  是否开启Debug模式
        'TESTING':                              False,                          是否开启测试模式
        'PROPAGATE_EXCEPTIONS':                 None,                          
        'PRESERVE_CONTEXT_ON_EXCEPTION':        None,
        'SECRET_KEY':                           None,
        'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),
        'USE_X_SENDFILE':                       False,
        'LOGGER_NAME':                          None,
        'LOGGER_HANDLER_POLICY':               'always',
        'SERVER_NAME':                          None,
        'APPLICATION_ROOT':                     None,
        '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,
        'MAX_CONTENT_LENGTH':                   None,
        'SEND_FILE_MAX_AGE_DEFAULT':            timedelta(hours=12),
        'TRAP_BAD_REQUEST_ERRORS':              False,
        'TRAP_HTTP_EXCEPTIONS':                 False,
        'EXPLAIN_TEMPLATE_LOADING':             False,
        'PREFERRED_URL_SCHEME':                 'http',
        'JSON_AS_ASCII':                        True,
        'JSON_SORT_KEYS':                       True,
        'JSONIFY_PRETTYPRINT_REGULAR':          True,
        'JSONIFY_MIMETYPE':                     'application/json',
        'TEMPLATES_AUTO_RELOAD':                None,
    }

2.使用方式

方式一:在app文件中直接使用(不推荐)

# 在app文件内直接使用
from flask import Flask 

app = Flask(__name__)
app.secret_key = 'xxxx'  # 设置session key
app.debug = True  # 设置debug

@app.route('/')
def hello_world():
    return 'Hello World!'

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

方式二:新建settings.py文件

  • settings.py中代码如下
class Config():
    DEBUG = False
    TESTING = False
    DATABASE_URI = 'sqlite://:memory:'


class ProductionConfig(Config):
'''继承自Config,不同的应用环境设置不同的配置项'''    
    DATABASE_URI = 'mysql://user@localhost/foo'
    
class DevelopmentConfig(Config):
    DEBUG = True
    
class TestingConfig(Config):
    TESTING = True
  • app.py中加入以下代码
app.config.from_object("python类或类的路径")
app.config.from_object('settings.TestingConfig')

三 | 路由系统

1.常用的路由系统

@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,
}

2.注册路由

方式一

def auth(func):
    def inner(*args, **kwargs):
        print('before')
        result = func(*args, **kwargs)
        print('after')
        return result
    return inner

@app.route('/index.html', methods=['GET', 'POST'], endpoint='index')
@auth
def index():
    return 'Index' 

方式二

def auth(func):
    def inner(*args, **kwargs):
        print('before')
        result = func(*args, **kwargs)
        print('after')
        return result
    return inner

class IndexView(views.MethodView):
    methods = ['GET']
    decorators = [auth, ]
    def get(self):
        return 'Index.GET'
    def post(self):
        return 'Index.POST'
app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  # name=endpoint

3.@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 strict_slashes=None,对URL最后的 / 符号是否严格要求
      @app.route('/index',strict_slashes=False)  # 访问 http://www.xx.com/index/ 或 http://www.xx.com/index均可
      @app.route('/index',strict_slashes=True)  # 仅访问 http://www.xx.com/index
7 redirect_to=None,  重定向到指定地址
      @app.route('/index/<int:nid>', redirect_to='/home/<nid>')
8 subdomain=None, 子域名访问

4.自定制正则路由匹配

from flask import Flask, views, url_for
from werkzeug.routing import BaseConverter
app = Flask(import_name=__name__)
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
    
# 添加到flask中
app.url_map.converters['regex'] = RegexConverter
@app.route('/index/<regex("\d+"):nid>')
def index(nid):
    print(url_for('index', nid='888'))
    return 'Index'
if __name__ == '__main__':
    app.run()

四 | 各种装饰器

1.*@app.before_request

类似django的process_request

@app.before_request
def before(*args,**kwargs):
     print('请求之前')
     '''
     如果允许通过访问,可以return None
     该装饰器装饰的函数如果有return其他内容则直接结束访问,
     效果有点类似django的process_reqeust中间件方法。
     比如通过这个装饰器写登陆验证,判断其是否有session,没有则不允许访问,有则继续访问
     然后通过request.path判断访问的函数,如果是登陆(白名单)则通过。
     request.url 是完整的url
     request.path是域名后面的url正则
     '''
     if request.path == '/login':
         return None
     user = session.get('user_info')
     if user:
         return None
     return redirect('/login')

2.*@app.after_request

类似django的process_response

 @app.after_request
 def after(response):
     #效果和process_response是一样的,必须有返回值,没有则报错。
     print('我走了')
     return response

3.@app.error_handlers(404)

自定义错误页面

 @app.error_handlers(404)
 def error_404(arg):
     '''自定义错误页面,根据状态码定制'''
     return "404错误啦"

4.@app.template_global()

前端直接调用后端函数的装饰器

 @app.template_global()
 def xx(a1,a2):
     return a1+a2
 '''
 这个装饰器的作用就是,可以在前端直接通过{{ xx(1,2)}}来调用后端的这个函数。
 '''

5.@app.template_filter()

相当于filter的装饰器

 @app.template_filter()
 def db(a1,a2,a3):
     return a1+a2+a3
 '''
 效果和django的Filter相似,前端渲染的时候需要注意写法
 {{ 1|db(2,3)}} 1是第一个参数,后面是2,3参数。
 '''

6.@app.before_first_request

第一次来请求操作的装饰器

 @app.before_first_request
 def first(*args,**kwargs):
     pass
 '''
 只有第一次请求时候才执行的函数装饰器
 '''

7.*flask中间件装饰器执行顺序

如果有多个app.before_request和app.after_request
那么执行顺序也和django类似,
app.before_request是按照从上而下执行(文件的上下),app.after_request是自下而上执行
如果在app.before_request中return了其他内容,请求被拦截,那么不会执行视图函数,
直接从最后一个app.after_reqeust倒着开始执行所有after_request。

五 | 模板

Flask模板语法和Django几乎无差别

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/login', methods=['GET', 'POST'])
def login():
      cont = {
              'name':'hao'
              'age':18
             }
    return render_template('login.html', **cont)  # 传参方式和jango区别,加**

app.run()

六 | 请求和响应

from flask import request, render_template, redirect, make_response

app = Flask(__name__)

@app.route('/login.html', methods=['GET', "POST"])
def login():
    # 请求相关信息 =====================================================================
    # *request.method  请求方法 'POST'、'GET'...
    # *request.args      获取GET值
    # *request.form      获取POST值  例:user = request.form.get('user')
    # 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()

七 | Session

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

1.session基本操作

app.secret_key = 'sdfasf'  # 设置secretkey,没有则无法设置session

session['username'] = 'xxx'  # 设置session,和django一样
value = session['username']  # 取session 方式一 
value = session.get('username') # 取session 方式二
session.pop('username', None)  # 删除session 方式一
del session['username']  # 删除session 方式二

2.session基本使用

from flask import Flask, session, redirect, url_for, escape, request

app = Flask(__name__)
@app.route('/')
def index():
    if 'username' in session:
        return 'Logged in as %s' % escape(session['username'])
    return 'You are not logged in'

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''
        <form action="" method="post">
            <p><input type=text name=username>
            <p><input type=submit value=Login>
        </form>
    '''

@app.route('/logout')
def logout():
    # remove the username from the session if it's there
    session.pop('username', None)
    return redirect(url_for('index'))
# set the secret key.  keep this really secret:
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'

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

3.自定义session和第三方session

[https://www.cnblogs.com/xingxingnbsp/p/12397155.html]

八 | 蓝图(blueprint)

1.小型程序

①目录结构

②run.py代码(启动文件)

from pro_flask import app

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

③__init__.py代码

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask
from .views.account import account
from .views.blog import blog
from .views.user import user

app=Flask(__name__,template_folder='templates',static_folder='statics',static_url_path='/static')
app.register_blueprint(account)
app.register_blueprint(blog)
app.register_blueprint(user)

④三个蓝图内代码

'''
_______
Account.py
_______
'''
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Blueprint
from flask import render_template
from flask import request

account = Blueprint('account', __name__)

@account.route('/login.html', methods=['GET', "POST"])
def login():
    return render_template('login.html')

'''
_______
blog.py
_______
'''
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Blueprint

blog = Blueprint('blog', __name__)

'''
_______
user.py
_______
'''
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Blueprint
user = Blueprint('user', __name__)

⑤Login.html代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>用户登录</h1>
<form method="POST">
    <input type="text" name="user"/>
    <input type="submit" value="提交"/>
</form>
<img src="/static/code.png">
<img src="{{ url_for('static',filename='code.png') }}">
</body>
</html>

2.大型程序


①run.py代码

from pro_flask import app

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

②__init__.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask
from .admin import admin
from .web import web
 
app = Flask(__name__)
app.debug = True
app.register_blueprint(admin, url_prefix='/admin')
app.register_blueprint(web)

③Admin/init.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Blueprint
admin = Blueprint('admin',__name__,template_folder='templates',static_folder='static')
from . import views

④Admin/views.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from . import admin
@admin.route('/index')
def index():
    return 'Admin.Index'

⑤Web/__init.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Blueprint
web = Blueprint('web',__name__,template_folder='templates',static_folder='static')
from . import views

⑥Web/views.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from . import web
@web.route('/index')
def index():
    return 'Web.Index'

九 | message

message是一个基于Session实现的用于保存数据的集合,其特点是:使用一次就删除。

from flask import Flask, flash, redirect, render_template, request, get_flashed_messages
app = Flask(__name__)
app.secret_key = 'some_secret'
@app.route('/')
def index1():
  messages = get_flashed_messages()
  print(messages)
  return "Index1"

@app.route('/set')
def index2():
  v = request.args.get('p')
  flash(v)
  return 'ok'

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

十 | 中间件

from flask import Flask, flash, redirect, render_template, request
app = Flask(__name__)
app.secret_key = 'some_secret'


@app.route('/')
def index1():
    return render_template('index.html')

@app.route('/set')
def index2():
    v = request.args.get('p')
    flash(v)
    return 'ok'
 
class MiddleWare:
    def __init__(self,wsgi_app):
        self.wsgi_app = wsgi_app

    def __call__(self, *args, **kwargs):
        return self.wsgi_app(*args, **kwargs)

if __name__ == "__main__":
    app.wsgi_app = MiddleWare(app.wsgi_app)
    app.run(port=9999)
posted @ 2020-11-30 19:45  顺才  阅读(89)  评论(0)    收藏  举报