簡體   English   中英

如何在sqlalchemy中提交之前應用列默認值

[英]How to apply Column defaults before a commit in sqlalchemy

我有一個聲明基礎模型:

class User(Base):
    id = Column(Integer, primary_key=True)
    money = Column(Integer, default=100)

然后我跑了

>>> u = User()
>>> u.money
None

如何在向數據庫寫入任何內容的情況下使用sqlalchemy填充默認值?

列默認僅適用於INSERT和UPDATE語句,因此直到您.flush()會話.flush()應用。

要在刷新之前在新實例上看到相同的值,您需要在創建新實例時應用默認值; User對象的__init__方法中:

class User(Base):
    __tablename__ = 'users'

    def __init__(self, **kwargs):
        if 'money' not in kwargs:
             kwargs['money'] = self.__table__.c.money.default.arg
        super(User, self).__init__(**kwargs)

    id = Column(Integer, primary_key=True)
    money = Column(Integer, default=100)

如果沒有設置money屬性,我們將根據為該列配置的默認值直接添加一個。

請注意,默認值是SQL表達式 ,而不是Python值,因此您可能必須首先將它們映射到Python對象。 例如,布爾字段將具有默認的'false''true'字符串值,而不是FalseTrue Python布爾對象。

我發現了一種在創建實例時自動填充某些默認值的機制。 我正在從內部ORM遷移,在實例創建時設置默認值,因此我需要保留此行為,我不想觸及每個模型定義。

BaseModel = declarative_base()

class Base(BaseModel):
    __abstract__ = True

    def __init__(self, **kwargs):
        for attr in self.__mapper__.column_attrs:
            if attr.key in kwargs:
                continue

            # TODO: Support more than one value in columns?
            assert len(attr.columns) == 1
            col = attr.columns[0]

            if col.default and not callable(col.default.arg):
                kwargs[attr.key] = col.default.arg

        super(Base, self).__init__(**kwargs)

主要限制是僅支持不可調用的默認值。 可調用默認值和使用數據庫查詢的默認值需要在實例創建時不可用的執行上下文。 另外,我還沒有發現len(ColumnProperty.columns) != 1的情況,但也不支持。

因為我需要默認值不一定在構造函數中,但有時來自其他地方,我想出了一個函數,我添加到我的基礎Object類:

Base = declarative_base()
class ItemBase(Base):
    __abstract__ = True
    def _ensure_defaults(self):
        for column in self.__table__.c:
            if getattr(self, column.name) is None and column.default is not None and column.default.is_scalar:
                setattr(self, column.name, column.default.arg)

這顯然不適用於callables。 我無法弄清楚如何調用它,也許它會變得更好(感覺就像已經破解了想法)。

有了這個,我可以這樣做:

class User(ItemBase):
    # ... inheritance, columns and stuff
    def __init__(self):
        self._ensure_defaults()

我也可以調用不在__init__的方法,也可以調用其他方法,以防我在特殊情況下只需依賴值(后來我最終刪除了,因為它太混亂了)。 在某些情況下,這可能比@JamesEmerton的解決方案更靈活。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM