Flask摘抄

功能函数

after_this_request

临时回调

from flask import request, after_this_request

@app.before_request
def detect_user_language():
    language = request.cookies.get('user_lang')
    
    if language is None:
        language = guess_language_from_request()
        
        @after_this_request
        def remember_language(response):
            response.set_cookie('user_lang', language)
            return response
            
    g.language = language

流处理

基础用法 - 基于生成器构建响应
from flask import Response

@app.route('large.csv')
def generate_large_csv():
    def generate():
        for row in iter_all_rows():
            yield ','.join(row) + '\n'
    return Response(generate(), mimetype='text/csv')
模板中使用
from flask import Response

def stream_template(template_name, **context):
     app.update_template_context(context)
     t = app.jinja_env.get_template(template_name)
     rv = t.stream(context)
     rv.enable_buffering(5)
     return rv

@app.route('/my-large-page.html')
def render_large_template():
    rows = iter_all_rows()
    return Response(stream_template('the_template.html', rows=rows))
情境中使用
from flask import stream_with_context, request, Response

@app.route('/stream')
def streamed_response():
    def generate():
        yield 'Hello '
        yield request.args['name']
        yield '!'
    return Response(stream_with_context(generate()))

添加页面图标

import os
from flask import send_from_directory

@app.route('/favicon.ico')
def favicon():
    return send_from_directory(os.path.join(app.root_path, 'static'),
                               'favicon.ico', mimetype='image/vnd.microsoft.icon')

连接MongoDB

构建连接
from flask import Flask
from flask_mongoengine import MongoEngine

app = Flask(__name__)
app.config['MONGO_SETTINGS'] = {
    'db': 'myapp',
}
db = MongoEngine(app)
映射文档
import mongoengine as me

class Movie(me.Document):
    title = me.StringField(required=True)
    year = me.IntField()
    rated = me.StringField()
    director = me.StringField()
    actors = me.ListField()

class Imdb(me.EmbeddedDocument):
    imdb_id = me.StringField()
    rating = me.DecimalField()
    votes = me.IntField()

class Movie(me.Document):
    ...
    imdb = me.EmbeddedDocumentField(Imdb)

创建数据
bttf = Movie(title='Back To The Future', year=1985)
bttf.actors = [
    'Michael J. Fox',
    'Christopher Lloyd'
]
bttf.imdb = Imdb(imdb_id='tt0088763', rate=8.5)
bttf.save()
查询数据

bttf = Movies.objects(title='Back To The Future').get_or_404()

some_theron_movie = Movie.objects(actors_in=['Charlize Theron']).first()

for recents in Movie.objects(year__gte=2017):
    print(recents.title)

惰性加载

  • STEP1: 分离视图文件

views.py

def index():
    pass

def user(username):
    pass

app.py

from flask import Flask
import views

app = Flask(__name__)
app.add_url_rule('/', view_func=views.index)
app.add_url_rule('/user/<username>', view_func=views.user)
  • STEP2: 添加延迟加载

lazyview.py

from werkzeug.utils import import_string, cached_property

class LazyView(object):
    def __init__(self, import_name):
        self.__module__, self.__name__ = import_name.rsplit('.', 1)
        self.import_name = import_name

    @cached_property
    def view(self):
        return import_string(self.import_name)
    
    def __call__(self, *args, **kwargs):
        return self.view(*args, **kwargs)

app.py

from flask import Flask
import views

app = Flask(__name__)
app.add_url_rule('/', view_func=LazyView('views.index'))
app.add_url_rule('/user/<username>', view_func=LazyView('views.user'))
  • STEP3: 代码优化

url.py

def url(import_name, url_rules=[], **options):
    view = LazyView(import_name)
    for url_rule in url_rules:
        app.add_url_rule(url_rule, view_func=view, **options)

url('views.index', ['/'])
url_rules = ['/user/', '/user/<username>']
url('views.user', url_rules)

自定义错误页面

常见的错误类型

  • 404 Not Found: 页面或者资源不存在
  • 403 Forbidden: 客户端未得到授权
  • 410 Gone: 页面或者资源已经删除
  • 500 Internal Server Error: 程序出错或者服务端过载
定义一个错误处理器
from flask import render_template

# 装饰器模式
@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404

# 工厂模式
def page_not_found(e):
    return render_template('404.html'), 404

def create_app(config_filename):
    app = Flask(__name__)
    app.register_error_handler(404, page_not_found)
    return app

# 返回json数据
from flask import abort, jsonify

@app.errorhandler(404)
def resource_not_found(e):
    return jsonify(error=str(e)), 404

@app.route('/cheese')
def get_one_cheese():
    resource = get_resource()
    
    if resource is None:
        abort(404, description='Resource not found')

    return jsonify(resource)

消息闪现

app.py

from flask import Flask, flash, redirect, render_template, \
    request, url_for

app = Flask(__name__)
app.scret_key = b'_5#y2L"F4Q8z\n\xec]/'

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

@app.route('/login', methods=['GET', 'POST'])
def login():
    error = None
    if request.method == 'POST':
        request.form['username'] != 'admin' or \
        request.form['password'] != 'secret':
            error = 'Invalid credentials'
    else:
        flash('You were successfully logged in')
        return redirect(url_for('index'))

    return render_template('login.html', error=error)

layout.html

<!DOCTYPE html>
<title>My Application</title>
{% with message = get_flasked_message() %}
    {% if message %}
        <ul class=flases>
        {% for message in messages %}
            <li>{{ message }}</li>
        {% endfor %}
        </ul>
    {% endif %}
{% endwith %}
定义闪现消息类型
flash(u'Invalid password provided', 'error')
{% with message = get_flashed_messages(with_categories=true) %}
    {% if message %}
        <ul class=flashes>
        {% for category, message in messages %}
            <li class="{{ category }}">{{ message }}</li>
        {% endfor %}
        </ul>
    {% endif %}
{% endwith %}
过滤闪现消息
{% with errors = get_flashed_message(category_filter=["error"]) %}
{% if errors %}
<div class="alert-message block-message error">
    <a class="close" href="#">
    <ul>
        {%- for msg in errors %}
            <li>{{ msg }}</li>
        {% endfor -%}
    </ul>
    </a>
</div>
{% endif %}
{% endwith %}

缓存

使用Flask-Caching扩展实现缓存。


from flask import Flask
from flask_caching import Cache

config = {
    "DEBUG": True,
    "CACHE_TYPE": "SimpleCache",
    "CACHE_DEFAULT_TIMEOUT": 300
}

app = Flask(__name__)
app.config.from_maping(config)
cache = Cache(app, config=config)
cache.init_app(app)

@app.route("/")
@cache.cached(timeout=50, key_prefix='all_comments')
def index():
    return render_template('index.html')

@cache.cached(timeout=50, key_prefix='all_comments')
def get_all_comments():
    comments = do_serious_dbio()
    return [x.author for x in comments]

cached_comments = get_all_comments()


class Person(db.Model):
    @cache.memoize(50)
    def has_membership(self, role_id):
        return Group.query.filter_by(user=self, role_id=role_id).count() >= 1

    def __repr__(self):
        return "%s(%s)" % (self.__class__.__name__, self.id)

class Foobar(object):
    @classmethod
    @cache.memoize(5)
    def big_foo(cla, a, b):
        return a + b + random.randrange(0, 100000)


cache.delete_memoized(Foobar.big_foo, Foobar, 5, 2)


class RedisCache(BaseCache):
    def __init__(self, servers, default_timeout=500):
         pass

    @classmethod
    def factory(cls, app, args, kwargs):
        args.append(app.config['REDIS_SERVERS'])
        return cls(*args, **kwargs)
              

上传文件

import os
from flask import Flask, flash, request, redirect, url_for, send_from_directory
from wekzeug.utils import secure_filename

UPLOAD_FOLDER =  '<path>'
ALLOW_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

def allowed_file(filename):
    return '.' in filename and \
        filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        if 'file' not in request.files:
            flash('No file part')
            return redirect(request.url)
        file = request.files['file']
        if file.filename == '':
            flash('No selected file')
            return redirect(request.url)
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            return redirect(url_for('upload_file', filename=filename)
    return '''
    <!doctype html>
    <title>Uplaod new File</title>
    <h1>Upload new File</h1>
    <form method=post enctype=multipart/form-data>
        <input type=file name=file>
        <input type=submit value=Upload>
    </form>
    '''

@app.route('/uploads/<filename>')
def uploaded_file(filename):
    return send_from_directory(app.config['UPLOAD_FOLDER'], filename)

URL处理器

from flask import Flask, g

app = Flask(__name__)

@app.route('/<lang_code>/')
def index(lang_code):
    g.lang_code = lang_code
    ...

@app.route('/<lang_code>/about')
def about(lang_code):
    g.lang_code = lang_code

@app.url_defaults
def add_language_code(endpoint, values):
    if 'lang_code' in values or not g.lang_code:
        return
    if app.url_map.is_endpoint_expecting(endpoint, 'lang_code'):
        values['lang_code'] = g.lang_code

@app.url_value_preprocessor
def pull_lang_code(endpoint, values):
    g.lang_code = values.pop('lang_code', None)

API异常处理

from flask import jsonify

class InvalidUsage(Exception):
    status_code = 404

    def __init__(self, message, status_code=None, payload=None):
        Exception.__init__(self)
        if status_code is not None:
            self.status_code = status_code
        self.payload = payload

    def to_dict(self):
        rv = dict(self.payload or ())
        rv['message'] = self.message
        return rv

@app.errorhandler(InvalidUsage)
def handle_invalid_useage(error):
    response = jsonify(error.to_dict())
    response.status_code = error.status_code
    return response

@app.route('/foo')
def get_foo():
    raise InvalidUsage('This view is gone', status_code=410)

应用工厂

def create_app(config_filename):
    app = Flask(__name__)
    app.config.from_pyfile(config_filename)

    from .model import db
    db.init_app(app)

    from .views.admin import admin
    from .views.frontend import frontend
    app.register_blueprint(admin)
    app.register_blueprint(frontend)

    return app

Flask继承

from flask import Flask, Request
from werkzeug.datastructures import ImmutableOrderedMultiDict

class MyRequest(Request):
    parameter_storage_class = ImmutableOrderedMultiDict

class MyFlask(Flask):
    request_class = MyRequest

单页面应用

from flask import Flask, jsonify

app = Flask(__name__, static_folder='app', static_url_path='/app')

@app.route('/heartbeat')
def heartbeat():
    return jsonify({'status': 'healthy'})

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def catch_all(path):
    return app.send_static_file('index.html')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值