首页 > 数据库 >重构 Flask 服务端项目对于 SQL 的配置使用和延迟的请求回调巧妙设计运用

重构 Flask 服务端项目对于 SQL 的配置使用和延迟的请求回调巧妙设计运用

时间:2022-10-28 20:33:29浏览次数:40  
标签:language Flask db request session SQL import 服务端

一. Flask-SQLAlchemy

SQLAlchemy的声明扩展是使用SQLAlchemy的最新方法,可以像Django一样在一个位置定义表和模型,然后在任何地方使用。

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:////tmp/test.db')
db_session = scoped_session(sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))
Base = declarative_base()
Base.query = db_session.query_property()

def init_db():
    import yourapplication.models
    Base.metadata.create_all(bind=engine)

在这里导入定义模型所需要的所有模块,这样它们就会正确的注册在元数据上。否则你就必须在调用 init_db() 之前导入它们。

要定义模型,只需继承上面创建的Base类。你可能会好奇,这里为什么不关心线程。(与SQLite3一样,使用G对象。)原因是SQLAlchemy已经用scoped_session为我们做了这样的事情。 要在应用程序中声明性地使用SQLAlchemy,只需将以下代码添加到应用程序模块中:Flask在请求结束或应用程序终止时自动删除数据库会话:

from yourapplication.database import db_session

@app.teardown_appcontext
def shutdown_session(exception=None):
    db_session.remove()

人工对象关系映射

人工对象关系映射与上述声明方式相比有优点和缺点。主要区别在于手动对象关系映射分别定义和映射表和类。这种方法更灵活,但需要更多的代码。通常,这种方法的运行方式与声明相同,因此必须将应用程序划分到包中的多个模块中。

from sqlalchemy import create_engine, MetaData
from sqlalchemy.orm import scoped_session, sessionmaker

engine = create_engine('sqlite:////tmp/test.db')
metadata = MetaData()
db_session = scoped_session(sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))
def init_db():
    metadata.create_all(bind=engine)

二. 延迟的请求回调

Flask的设计思想之一是,在创建响应对象之后,它被传递给一系列回调函数,这些回调函数可以修改或替换响应对象。请求处理开始时,尚未创建响应对象。响应对象由视图函数或系统中的其他组件按需创建。 但是,当响应对象尚未创建时,我们如何修改它呢?例如,在request()回调函数中,我们需要根据响应对象设置一个cookie。

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()

        # when the response exists, set a cookie with the language
        @after_this_request
        def remember_language(response):
            response.set_cookie('user_lang', language)
            return response

    g.language = language

通常我们选择避免这种情况。例如,可以尝试将应用程序逻辑移动到after_Therequest()回调函数。然而,有时这种方法令人不快,或者使代码难看。 另一种方法是使用after_this_ request()回调函数,该函数仅在当前请求之后执行。这允许您在应用程序中的任何位置延迟回调函数的执行。 在请求中的任何时候,您都可以注册将在请求结束时调用的函数。例如,下面的示例显示在before_ request()回调函数会记住cookie中当前用户的语言:

基于 Celery 的后台任务

首先,需要有一个Celery实例,称为Celery应用程序。它的状态与Flask中的Flask相同。此实例用作所有与Celery相关的事务的条目,例如创建任务和管理工人,因此它必须由其他模块导入。 例如,可以将其放在任务模块中。通过这种方式,您可以使用任务的子类,添加对Flask应用程序场景的支持,并且无需重新配置即可挂接Flask配置。 酒窖可以在福尔斯克使用,只要:

from celery import Celery

def make_celery(app):
    celery = Celery(
        app.import_name,
        backend=app.config['CELERY_RESULT_BACKEND'],
        broker=app.config['CELERY_BROKER_URL']
    )
    celery.conf.update(app.config)

    class ContextTask(celery.Task):
        def __call__(self, *args, **kwargs):
            with app.app_context():
                return self.run(*args, **kwargs)

    celery.Task = ContextTask
    return celery

此函数创建一个新的Celery对象,在应用程序配置中使用代理,并从Flask配置中更新剩余的Celey配置。然后创建任务子类,将任务执行打包到应用程序上下文中。

挂接,扩展

API文档可以在任何地方看到可用的重载、挂钩点和信号。您可以自定义自定义类,例如请求或响应对象。请深入研究您使用的API,以及哪些可定制部件可用于Flask分发。请研究哪些项目可以重构为工具集或Flask扩展。您可以在社区中找到许多扩展。如果你找不到满意的东西,就自己写一篇。

继承 Flask

from flask import Flask, Request
from werkzeug.datastructures import ImmutableOrderedMultiDict
class MyRequest(Request):
    """Request subclass to override request parameter storage"""
    parameter_storage_class = ImmutableOrderedMultiDict
class MyFlask(Flask):
    """Flask subclass using the custom request class"""
    request_class = MyRequest

以这种方式重载或者增强 Flask 的内部功能。

标签:language,Flask,db,request,session,SQL,import,服务端
From: https://blog.51cto.com/u_15568258/5802009

相关文章

  • 常见的MySQL面试题有哪些?
    本文主要介绍我在公司招聘的时候,主要问应聘者的一些问题,希望对换工作的同行及在使用过程中有些疑问的同行有所帮助1. MySQL海量数据优化优化问题主要从SQL优化、事务级别调......
  • MySQL--常用语句
    MySQL常用语句1、获取数据库信息1.use数据库名;//选择要操作的Mysql数据库,使用该命令后所有Mysql命令都只针对该数据库。2.showdatabases;//列出MySQL数据库管理......
  • 【SpringBoot】引入mybatis及连接Mysql数据库
    创建一个SpringBoot项目其他不赘叙了,引入MyBaties、MySql依赖编辑 创建mysql表CREATETABLEsp_users(`id`INTPRIMARYKEY,`username`VARCHAR(30),`age`INT);刚......
  • sqlserver and or 的区别
    sqlserverandor的区别Or不加括号:查询结果36条数据,BID=21,BID=25匹配的Status的数据都会查询出来 selectBID,TradeID,[status],PaymentToBIdfromTradewhereBID......
  • sqlserver between
     sqlserverbetween----如果UpdateTime为''或者为null,就用InsertTime条件查询select*fromWxUserswhereBID='957'andParentID='5537821'and(COALESCE(UpdateT......
  • sqlserver2016安装包简要说明
    sqlserver2016安装包简要说明如果要装vs,先装了sqlserver数据库再装vs,因为vs自带了sqlserver简版,会和sqlserver2016有冲突。 先装sqlserver内核    然后装管......
  • sql server 中有哪几种约束?
    sqlserver中有哪几种约束? 一共有六种约束:这里以学生表stuinfo为例1、添加主键约束altertablestuinfoaddcostraintpk_stunoprimarykey(stuno)2、2、唯一约......
  • sqlserver索引和约束
     sqlserver索引和约束 ==========================================================----查找索引----usedatabase_nameEXECSp_helpindextable_nameuseTeama......
  • 视频融合平台EasyCVR如何操作MySQL数据库来批量关闭通道?
    EasyCVR具备强大的视频接入、汇聚与管理、视频分发等视频能力,可实现的视频功能包括:视频监控直播、云端录像、云存储、录像检索与回看、智能告警、平台级联、服务器集群、智......
  • MSSQL三表/两表联合查询
    两张表的联合查询语句select* from User101219_Expandinnerjoin  user_101445onUser101219_Expand.userid=user_101445.userid 三表联合查询语句select* f......