Skip to content Skip to sidebar Skip to footer

SQLAlchemy Best Way To Define __repr__ For Large Tables

I have a bunch of tables in SQLAlchemy that I want to define __repr__. The standard convention seems to look like this: def __repr__(self): return ''

Solution 1:

Having good __repr__ for complex objects can be incredibly useful when navigating log files and stacktraces, so it's great that you're trying to come up with a good pattern for it.

I like to have a little helper with a default (BaseModel gets set as the model_class when initializing flask-sqlalchemy in my case).

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

Now you can keep your __repr__ methods nice and neat:

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)

Should produce something like:

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


Post a Comment for "SQLAlchemy Best Way To Define __repr__ For Large Tables"