SQLAlchemy 为大表定义 __repr__ 的最佳方法

Int*_*rer 6 python sqlalchemy repr

我在 SQLAlchemy 中有一堆要定义的表__repr__

标准约定似乎是这样的:

def __repr__(self):
    return "<TableName(id='%s')>" % self.id
Run Code Online (Sandbox Code Playgroud)

这对小桌子来说都很好。但是,我有 40 多列的表格。 有没有更好的构造方法,__repr__这样我就不用手动输入大量字符串?

我的包含所有表的文件称为models.py. 一种解决方案我想到了制作方法,_create_repr_stringmodels.py该负责自动生成的字符串进行__repr__返回。我想知道是否有更标准的方法来创建__repr__.

Ste*_*hry 13

__repr__导航日志文件和堆栈跟踪时,对复杂对象有好处是非常有用的,所以尝试为它想出一个好的模式是很棒的。

我喜欢有一个默认的小帮手(在我的情况下,BaseModel 被设置为model_class初始化flask-sqlalchemy时)。

import typing
import sqlalchemy as sa

class BaseModel(Model):

    def __repr__(self) -> str:
        return self._repr(id=self.id)

    def _repr(self, **fields: typing.Dict[str, typing.Any]) -> str:
        '''
        Helper for __repr__
        '''
        field_strings = []
        at_least_one_attached_attribute = False
        for key, field in fields.items():
            try:
                field_strings.append(f'{key}={field!r}')
            except sa.orm.exc.DetachedInstanceError:
                field_strings.append(f'{key}=DetachedInstanceError')
            else:
                at_least_one_attached_attribute = True
        if at_least_one_attached_attribute:
            return f"<{self.__class__.__name__}({','.join(field_strings)})>"
        return f"<{self.__class__.__name__} {id(self)}>"
Run Code Online (Sandbox Code Playgroud)

现在你可以让你的__repr__方法保持整洁:

class MyModel(db.Model):

    def __repr__(self):
        # easy to override, and it'll honor __repr__ in foreign relationships
        return self._repr(id=self.id,
                          user=self.user,
                          blah=self.blah)
Run Code Online (Sandbox Code Playgroud)

应该产生类似的东西:

<MyModel(id=1829,user=<User(id=21, email='foo@bar.com')>,blah='hi')>

  • 我喜欢这种方法的可定制性,谢谢! (2认同)
  • @p6l-richard 从常用的“sqlalchemy.ext.declarative.declarative_base()”*和*Stephen Fuhry 编写的“BaseModel”类继承您的类。`BaseModel` 本身不需要继承自 `Model` - 它可以是独立的。 (2认同)