首页 > 解决方案 > 琐碎更改后在应用程序上下文之外烧瓶

问题描述

我有一个运行良好的应用程序,然后我添加了几行代码,这些代码在逻辑上与已经存在的一些代码相同,然后我突然摆脱了应用程序上下文错误。

该代码试图从 current_app.config 中获取一个新的配置变量。当它起作用时,它已经有了这样的变量。

这行得通,观察current_app.config['SECRET_KEY']因此行得通。

**config.py**
...
class Config(object):
    ...
    SECRET_KEY = os.getenv('SECRET_KEY') or \
        'yaP5vdVON2IlssoL3OZEo41P2MXJo6hx'
    ...

**models.py**
...
from flask import current_app
...

class User(UserMixin, db.Model):
    __bind_key__ = 'app'
    __tablename__ = 'user'
    )
    tennant_id = db.Column(db.ForeignKey('_constants.tennant_id'), nullable=False, index=True)
    user_id = db.Column(db.Integer, primary_key=True)
    identity_id = db.Column(db.Integer, index=True)
    ...
    def get_reset_password_token(self, expires_in=600):
        return jwt.encode(
            {'reset_password': self.user_id, 'exp': time() + expires_in},
            current_app.config['SECRET_KEY'],
            algorithm='HS256').decode('utf-8')

以下不起作用RELATIONSHIP_FOLLOW_TYPE,请注意配置变量的处理方式和处理方式没有明显差异MESSAGE_POST_TYPE

此外,我曾经在代码中使用这些变量的显式声明版本,所以代码可以工作!

**config.py**
...
class Config(object):
    ...
    SECRET_KEY = os.getenv('SECRET_KEY') or \
        'yaP5vdVON2IlssoL3OZEo41P2MXJo6hx'
    ...
    MESSAGE_POST_TYPE = 2
    RELATIONSHIP_FOLLOW_TYPE = 1
    ...

**models.py**
...
from flask import current_app
...

class User(UserMixin, db.Model):
    __bind_key__ = 'app'
    __tablename__ = 'user'
    )
    tennant_id = db.Column(db.ForeignKey('_constants.tennant_id'), nullable=False, index=True)
    user_id = db.Column(db.Integer, primary_key=True)
    identity_id = db.Column(db.Integer, index=True)
    ...
    def get_reset_password_token(self, expires_in=600):
        return jwt.encode(
            {'reset_password': self.user_id, 'exp': time() + expires_in},
            current_app.config['SECRET_KEY'],
            algorithm='HS256').decode('utf-8')
    ...       
    def followed_posts(self):
        followed = Message.query.join(
            Relationship, 
            (Relationship.related_user_id == Message.sender_id)). \
            filter(Relationship.user_id == self.user_id). \
            filter(Relationship.relationship_type_id == current_app.config['RELATIONSHIP_FOLLOW_TYPE']). \
            filter(Message.message_type_id == current_app.config['MESSAGE_POST_TYPE'])
        own = Message.query.filter_by(
            sender_id = self.user_id,
            message_type_id = current_app.config['MESSAGE_POST_TYPE'])
        return followed.union(own).order_by(Message.timestamp.desc())

我已经尝试了一切!尤其是: -

  1. 我回到代码的旧工作版本,手动将配置变量添加到 Config,手动将从配置中读取的变量的用法添加到 models.py 中,并且成功了!我看不出代码之间的差异!
  2. 在我的新的非工作代码中,我将两个新的配置变量恢复为显式声明,代码运行直到它命中之后的下一个current_app.config变量,换句话说,适用于 但不适用于and 。SECRET_KEYcurrent_app.configSECRET_KEYRELATIONSHIP_FOLLOW_TYPEMESSAGE_POST_TYPE

显然我必须做一些非常愚蠢的事情。有人可以指出我在任何地方或任何可能发生这种情况的原因。任何建议表示赞赏。

标签: flask

解决方案


这不是一个非常令人满意的答案,但我会解释我做了什么,如果有人有更好的答案,请随时发布。

  1. 我在我的 config.py 模块中创建了一个名为 Globals 的新类。
  2. 我将所有新的配置变量从 Config 移到了 Globals。在此 Config 恢复到应用程序工作时的方式之后,Globals 是一个新类。
  3. 我更新了所有代码以从 Globals 中获取新的配置变量,并从 Config 中获取所有原始变量。所以我为 Globals 添加了一个导入,只保留了 current_app 的导入。
  4. 我更改了变量的名称以根据需要引用全局配置变量或配置变量。
  5. 我没有移动任何代码,也没有进行任何其他更改。

尽管这不应该奏效,但它确实奏效了。

为了进一步测试,我在 Config 类中添加了一些虚拟配置变量,它们现在可以工作了!长话短说,我不知道出了什么问题,但是以这种方式解决了问题。

事后看来,区分真正的配置变量和应用程序参数可能不是一个坏主意,因此 Config 和 Globals 类可能是个好主意。


推荐阅读