在Flas中建立持久复杂对象的正确方法

2024-05-03 23:06:17 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在寻找关于如何处理烧瓶中的持久性对象的“良好实践”建议。在

我有自己的类来处理用户、组、组中的用户成员资格和用户/组权限。其中,有一个Passport类,它保存有关当前用户及其权限的信息。在

其思想是,每个用户会话都应该与它自己的Passport对象相关联,该对象在视图中持续存在:这样用户登录时就可以初始化某些权限,并且可以在以后使用视图和执行AJAX请求时进行检查。在

目前,我在Passport类中有序列化和反序列化方法,还有一个在视图.py全局范围,它具有只读的“passport”属性,该属性从会话变量读取序列化的passport数据并返回反序列化的对象。它有一个save()方法,它的作用正好相反。这个FlaskPassport类还有一个用于检查权限的视图的decorator方法。而且,提供对存储在会话中序列化状态的passport数据的访问的代码看起来相当笨拙。passport对象在更改后必须手动保存这一事实似乎并不正确—应该是这样,Flask会在自动处理请求后将修改后的passport对象保存到会话中。在

因此,我正在寻找一些聪明的模式,它将提供对全局passport对象的访问,所有视图都可以访问,并且还允许我向需要权限检查的视图添加装饰器。在


Tags: 数据对象方法用户视图权限属性序列化
1条回答
网友
1楼 · 发布于 2024-05-03 23:06:17

有多种方法可以做到这一点,包括:

  1. passport实例存储在g上,并使用before_request和{}处理程序对从会话到会话对实例进行水合/序列化:

    @app.before_request
    def load_passport():
        if "passport_id" in session:
            g.passport = create_passport_from_id(session["passport_id"])
    
    @app.after_request
    def serialize_passport(response):
        if hasattr(g, "passport"):
            session["passport_id"] = g.passport.id
        return response
    
  2. 使用Flask用于requestg(以及其他)的线程局部模式。在幕后,它使用了Werkzeug的LocalProxy,它安装在应用程序上下文或请求上下文上(取决于底层对象的生存期):

    from flask import (_request_ctx_stack as request_ctx,
                       has_request_context, session)
    from werkzeug.local import LocalProxy
    
    current_passport = LocalProxy(get_passport)
    
    def get_passport():
        if has_request_context() and "passport_id" in session:
            if not hasattr(request_ct.top, "passport"):
                passport_id = session["passport_id"]
                request_ctx.top.passport = construct_passport_from_id(passport_id)
             return getattr(request_ctx.top, "passport", None)
        return EmptyPassport()
    
    @app.after_request
    def serialize(response):
        if current_passport.is_not_empty():
            session["passport_id"] = current_passport.id
        return response
    

值得注意的是,我选择不将整个passport序列化到会话中,因为每个请求都会来回传递这些信息(取决于您在passport中存储了多少信息,这可能是您关心的问题,也可能不是您关心的问题)。在

还值得注意的是,这两种方法本身都不安全。Flask确实对会话cookie进行了签名以防篡改,但您仍然需要担心注销、新鲜度等问题。请查看Flask-Login's code中的其他一些您需要考虑的事项。在

相关问题 更多 >