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 "<TableName(id='%s')>" % self.id
This is all well and good for small tables. However, I have tables with 40+ columns. Is there a better way of constructing __repr__
such that I am not manually typing out a massive string?
My file housing all tables is called models.py
. One solution I thought about was making a method _create_repr_string
in models.py
that takes care of auto-generating the string for __repr__
to return. I am wondering if there is a more standard way to create __repr__
.
In Python, __repr__ is a special method used to represent a class's objects as a string. __repr__ is called by the repr() built-in function. You can define your own string representation of your class objects using the __repr__ method. Special methods are a set of predefined methods used to enrich your classes.
The psycopg2 is over 2x faster than SQLAlchemy on small table. This behavior is expected as psycopg2 is a database driver for postgresql while SQLAlchemy is general ORM library.
PyODBC allows you connecting to and using an ODBC database using the standard DB API 2.0. SQL Alchemy is a toolkit that resides one level higher than that and provides a variety of features: Object-relational mapping (ORM) Query constructions.
__repr__(self) : called by the repr() built-in function and by string conversions (reverse quotes) to compute the "official" string representation of an object. object. __str__(self) : called by the str() build-in function and by the print statement to compute the "informal" string representation of an object.
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='[email protected]')>,blah='hi')>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With