Reputation: 47
I'm writing the history of attribute changes for sqlalchemy
models. Attributes list, which are important for history, I keep in the class attribute history_attributes.
from sqlalchemy import Integer, Column, String
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class HistoryAttribute:
def __init__(self, descriptor, display_name, use_message=False):
self.name = descriptor.name
self.display_name = display_name
self.use_message = use_message
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
first_name = Column(String(100))
email = Column(String(100))
history_attributes = (
HistoryAttribute(descriptor=first_name, display_name='User name'),
email
)
print(User.history_attributes[0].name)
>>> None
print(User.history_attributes[1].name)
>>> email
Why does the attribute "name"
of the Column
instance disappear, if I pass one to constructor of other class? Of course, I can write first_name = Column('first_name', String(100)
and code will work fine,
but I don't want to add Column.name
explicitly. I avoided the problem using namedtuple, which I then pass to the constructor of the HistoryAttribute
class, but it's very similar to a crutch.
Upvotes: 1
Views: 202
Reputation: 6489
As has been discussed, the issue is that first_name.name
is set while the class is being constructed.
SQLAlchemy does have a mechanism for deferring an attribute definition until configuration time. Try something like
class User(Base):
# ...
@sqlalchemy.ext.declarative.api.declared_attr
def history_attributes(self):
return (HistoryAttribute(self.first_name #...))
That will defer the construction of history_attributes until a point where column names are populated
Upvotes: 1
Reputation: 20508
It's not that the name
attribute disappears, but that it hasn't been initialized yet. Look at the value of first_name
as passed to HistoryAttribute
: Column(String(100))
; it does not contain any mention of the string first_name
. SQLAlchemy will fill the name in later after the class is defined.
Upvotes: 3