一 Flask请求和响应

from flask import Flask
from flask import request
from flask import render_template
from flask import redirect
from flask import make_response

app = Flask(__name__)


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

请求相关信息

# request.method
# request.args          获取GET方式的url参数
# request.form          form提交的数据取值
# request.values        同时获得form和args的值
# request.json          请求头是contenttype:application/json 将字典序列化成jason
# request.data          contenttype请求无法解析时会以byte放入data
# 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 jsonfiy                 返回序列化的json数据
# return send_file(file_name)   返回一个文件

二 模板语言

1、模板的使用

Flask使用的是Jinja2模板,所以其语法和Django无差别

2、自定义模板方法

Flask中自定义模板方法的方式和Bottle相似,创建一个函数并通过参数的形式传入render_template,如:

from flask import Flask,url_for,request,redirect,render_template,jsonify,make_response,Markup
from urllib.parse import urlencode,quote,unquote
app = Flask(__name__)

def test(a1,a2):
    return a1+a2

@app.template_global()
def sb(a1,a2):
    return a1 + a2 + 100


@app.template_filter()
def db(a1, a2, a3):
    return a1 + a2 + a3


@app.route('/index',endpoint='xx')
def index():
    v1 = "字符串"
    v2 = [11,22,33]
    v3 = {'k1':'v1','k2':'v2'}
    v4 = Markup("<input type='text' />")
    return render_template('index.html',v1=v1,v2=v2,v3=v3,v4=v4,test=test)

'''
函数模板
'''
from common.libs.UrlManager import UrlManager

app.add_template_global(UrlManager.buildStaticUrl, 'buildStaticUrl')
app.add_template_global(UrlManager.buildUrl, 'buildUrl')
app.add_template_global(UrlManager.buildImageUrl, 'buildImageUrl')

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

layout.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>模板</h1>
    {%block body %} {%endblock%}

</body>
</html>

index.html

{% extends 'layout.html'%}

{%block body %}
    {{v1}}

    <ul>
        {% for item in v2 %}
        <li>{{item}}</li>
        {% endfor %}
    </ul>
    {{v2.1}}

    <ul>
        {% for k,v in v3.items() %}
        <li>{{k}}  {{v}}</li>
        {% endfor %}
    </ul>
    {{v3.k1}}
    {{v3.get('k1')}}

    {{v4}}
    <!--{{v4|safe}}-->

    <h1>{{test(1,19)}}</h1>

    {{sb(1,2)}}

    {{ 1|db(2,3)}}


    {% macro xxxx(name, type='text', value='') %}
        <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
        <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
        <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
        <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
    {% endmacro %}

    {{ xxxx('n1') }}


{%endblock%}

三 session

当请求刚到来时:Flask会读取cookie中session对应的值。 将这个值解密并反序列化成字典放入内存以便视图函数使用

视图函数:

@app.route('/ses')
def ses():
    session['k1'] = 123
    session['k2'] = 456
    del session['k1']
    return session

# 注意要在使用之前设置secret key 

app.secret_key = 'sdfsdfsdf'

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

四 闪现

闪现是指在session中存储一个数据,读取时通过pop将数据移除

from flask import Flask,flash,get_flashed_messages

@app.route('/page1')
def page1():
    flash('临时数据存储', 'error')
    flash('sdfsdfsdffsdf', 'error')
    flash('asdfsdfsdfdsf', 'info')
    
    return "Session"

@app.route('/page2')
def page2():
    print(get_flashed_messages(category_filter=['error']))
    return "Session"

 五 中间件

在call方法执行之前加入其它功能,实现类似中间件的功能
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):
        #  在call方法执行之前加入其它功能,实现类似中间件的功能
        return self.wsgi_app(*args, **kwargs)
 
if __name__ == "__main__":
    app.wsgi_app = MiddleWare(app.wsgi_app)
    app.run(port=9999)

六 特殊装饰器

  • - before_firset_request
  • - before_request # 再请求进入视图函数之前做出处理
  • - after_request # 再请求结束视图函数之后,返回客户端之前 def go(response) return response 逆向执行    # 正常场景be1-be2-af2-af1 异常场景 be1-af2-af1
  • - template_global()
  • - template_filter()
  • - errorhandler (404) # 在使用errorheadler传递参数 404 500 error(code_or_exp) return redirect("/index")

 拦截验证用户是否登录的方法:

# -*- coding: utf-8 -*-
from application import app
from flask import request,g,redirect

from common.models.User import ( User )
from common.libs.user.UserService import ( UserService )
from common.libs.UrlManager import ( UrlManager )
from common.libs.LogService import LogService
import  re
@app.before_request
def before_request(): ignore_urls = app.config['IGNORE_URLS'] ignore_check_login_urls = app.config['IGNORE_CHECK_LOGIN_URLS'] path = request.path # 如果是静态文件就不要查询用户信息了 pattern = re.compile('%s' % "|".join(ignore_check_login_urls)) if pattern.match(path): return if '/api' in path: return user_info = check_login() g.current_user = None if user_info: g.current_user = user_info # #加入日志 # LogService.addAccessLog() pattern = re.compile('%s' % "|".join(ignore_urls)) if pattern.match(path): return if not user_info : return redirect( UrlManager.buildUrl( "/user/login" ) ) return ''' 判断用户是否已经登录 ''' def check_login(): cookies = request.cookies auth_cookie = cookies[app.config['AUTH_COOKIE_NAME']] if app.config['AUTH_COOKIE_NAME'] in cookies else None if '/api' in request.path: app.logger.info(request.path) auth_cookie = request.headers.get("Authorization") app.logger.info( request.headers.get("Authorization") ) if auth_cookie is None: return False auth_info = auth_cookie.split("#") if len(auth_info) != 2: return False try: user_info = User.query.filter_by(uid=auth_info[1]).first() except Exception: return False if user_info is None: return False if auth_info[0] != UserService.geneAuthCode( user_info ): return False if user_info.status != 1: return False return user_info

404错误拦截

# -*- coding: utf-8 -*-
from application import app
from common.libs.Helper import ops_render
from common.libs.LogService import LogService

@app.errorhandler(404)
def error_404(e):
    LogService.addErrorLog(str(e))
    return ops_render('error/error.html', {'status': 404, 'msg': '很抱歉!您访问的页面不存在'})

七 蓝图

简单来说,Blueprint 是一个存储操作方法的容器,这些操作在这个Blueprint 被注册到一个应用之后就可以被调用,Flask 可以通过Blueprint来组织URL以及处理请求。

Flask使用Blueprint让应用实现模块化,在Flask中,Blueprint具有如下属性:

  • 一个应用可以具有多个Blueprint
  • 可以将一个Blueprint注册到任何一个未使用的URL下比如 “/”、“/sample”或者子域名
  • 在一个应用中,一个模块可以注册多次
  • Blueprint可以单独具有自己的模板、静态文件或者其它的通用操作方法,它并不是必须要实现应用的视图和函数的
  • 在一个应用初始化时,就应该要注册需要使用的Blueprint

但是一个Blueprint并不是一个完整的应用,它不能独立于应用运行,而必须要注册到某一个应用中。

使用蓝图的实例:

  

结构:
Mycrm
  crm
    static
    template
      login.html
    views
      account.py
      order.py
    models.py
    __init__.py
  manage.py
  settings.py

  

__init__.py:

from flask import Flask
from .views import account
from .views import order

app = Flask(__name__)
print(app.root_path)
# 注意一定要注册注册蓝图
app.register_blueprint(account.account)
app.register_blueprint(order.order)

manage.py:

import crm
if __name__ == '__main__'
    mycrm.app.runn()

account.py:

from flask import Blueprint,render_template
account = Blueprint('account',__name__,)

@account.route('/login')
def login():
    # return 'Login'
    return render_template('login.html')

order.py:

from flask import Blueprint

order = Blueprint('order',__name__)
@order.route('/order')
def login():
    return 'Order'

 

posted on 2019-07-09 18:09  cs_1993  阅读(311)  评论(0编辑  收藏  举报