SQLAlchemy大表定义__repr__的最佳方法是什么?

12

我在SQLAlchemy中有许多表格,我想定义 __repr__

标准的约定似乎是这样的:

def __repr__(self):
    return "<TableName(id='%s')>" % self.id

对于小型表格,这都很好。但是我有包含40多列的表格。有没有更好的构造方式可以创建__repr__以避免手动键入庞大的字符串?

我的所有表所在的文件名为models.py。我考虑的一个解决方案是在models.py中创建一个方法_create_repr_string来自动生成__repr__返回的字符串。我想知道是否有更标准的方法来创建__repr__


2
嗨,最近我回答了一个类似的问题:https://dev59.com/ArDma4cB1Zd3GeqPCt_I#54034230 - SuperShoot
1
看一下这个ReprMixin,你可以添加到你的基类中:https://github.com/absent1706/sqlalchemy-mixins#beauty-__repr__ - Michael Gendin
1个回答

23

当处理日志文件和堆栈跟踪时,为复杂对象编写良好的__repr__非常有用,因此很高兴您正在尝试寻找良好的模式。

我喜欢使用一个小助手并设置默认值(在我的情况下,在初始化flask-sqlalchemy时将model_class设置为BaseModel)。

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)}>"

现在您可以保持__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)

应该产生如下结果:

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


2
我喜欢这种方法的可定制性,谢谢! - Intrastellar Explorer
我想在Flask中实现你的帮助程序,但遇到了以下错误: sqlalchemy.exc.ArgumentError: Mapper mapped class BaseModel->base_model could not assemble any primary key columns for mapped table 'base_model'是否有一个适合初学者的解释,如何在不遇到此错误的情况下实现您的帮助程序? - p6l-richard
3
将您的类从通常的 sqlalchemy.ext.declarative.declarative_base() 和 Stephen Fuhry 编写的 BaseModel 类继承。BaseModel 本身不需要继承 Model - 它可以是独立的。 - Adam Ryczkowski
**fields: typing.Dict[str, typing.Any] 可能只需要写成 **fields: typing.Any - Dmitry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接