SQLAlchemy лучший способ определить __repr__ для больших таблиц - PullRequest
1 голос
/ 16 апреля 2019

У меня есть несколько таблиц в SQLAlchemy, которые я хочу определить __repr__.

Стандартное соглашение выглядит следующим образом:

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

Это все хорошодля маленьких столиков.Тем не менее, у меня есть таблицы с 40+ столбцами. Есть ли лучший способ построения __repr__, чтобы я не печатал вручную массивную строку?

Мой файл, содержащий все таблицы, называется models.py.Одним из решений, о котором я думал, было создание метода _create_repr_string в models.py, который позаботится об автоматической генерации строки для возврата __repr__.Мне интересно, есть ли более стандартный способ создания __repr__.

1 Ответ

1 голос
/ 18 апреля 2019

Наличие хороших __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)}>"

Теперь вы можете сохранять свои методы __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')>

...