Reputation: 1019
I have a class:
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class DataFromWeb(Base):
__tablename__ = 'data'
id = Column(Integer, primary_key=True)
name = Column(String(50))
Now I'm getting from the web a JSON array which also have several other fields (in which obviously I'm not interested in, and could change but shouldn't break the app).
This is the error: TypeError: 'timestamp' is an invalid keyword argument for DataFromWeb
. But there could be more fields. I'm just not interested in them.
Is there a nice way to ignore them? Or tell SQLAlchemy that the Column
s I've given are the only ones I'm interested in?
One way I found is this:
def __init__(self, *args, **kwargs):
# Gotta clean up the kwargs here :(
kwargs2 = {k: v for k, v in kwargs.items() if hasattr(self.__class__, k)}
super().__init__(*args, **kwargs2)
But this is just ugly in my opinion...
Thanks!
Upvotes: 2
Views: 868
Reputation: 55854
The default constructor for declarative models essentially performs the same hasattr
loop as that in the question, but raises a TypeError
if a kwargs key doesn't map to the name of an instance attribute, so the ugliness is unavoidable.
However, it can be hidden. declarative_base
accepts a constructor argument which will override the default constructor, so you could provide your own implementation which ignores unknown names. This way, you don't have to implement an __init__
method on all your models to filter unwanted keys.
def _declarative_constructor(self, **kwargs):
"""Don't raise a TypeError for unknown attribute names."""
cls_ = type(self)
for k in kwargs:
if not hasattr(cls_, k):
continue
setattr(self, k, kwargs[k])
Base = declarative_base(constructor=_declarative_constructor)
class DataFromWeb(Base):
__tablename__ = 'data'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String)
def __init__(self, *args, **kwargs):
# We don't really need an __init__ method, this is just
# for demonstration purposes.
super().__init__(*args, **kwargs)
Upvotes: 1