1

I have a table with the column TS_TEST_ID. I have a SQLAlchemy model with the following property:

id = Column(u'TS_TEST_ID', INTEGER(), primary_key=True, nullable=False)

Is there any way to set id on an instance of my model class when only TS_TEST_ID is known? That is, I only know the name of the column in the database, and I want to somehow map that to id and set the id property on my model. I was hoping just doing MyModel(**{'TS_TEST_ID':1}) would work, but I get the following error:

Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "<string>", line 4, in __init__
 File "C:\Python26\lib\site-packages\sqlalchemy\orm\state.py", line 111,
 in initialize_instance
 return manager.events.original_init(*mixed[1:], **kwargs)
 File "C:\Python26\lib\site-packages\sqlalchemy\ext\declarative.py", line 1377,
 in _declarative_constructor
 (k, cls_.__name__))
TypeError: 'TS_TEST_ID' is an invalid keyword argument for MyModel

I would rather not have to define TS_TEST_ID = Column(u'TS_TEST_ID', INTEGER(), primary_key=True, nullable=False) for every column in my model, either, or even a method called TS_TEST_ID that returns the id property.

Ilja Everilä
53.3k9 gold badges137 silver badges141 bronze badges
asked Jun 29, 2011 at 15:33
2
  • 1
    Can't check it anywere, so just a wild guess: does yourobj.c.TS_TEST_ID = 15 do the trick? Commented Jun 29, 2011 at 15:51
  • An instance of MyModel doesn't have a c property, but I can access the same thing (I think) through myobj.__mapper__.c, and trying to access myobj.__mapper__.c.TS_TEST_ID fails with an AttributeError. Commented Jun 29, 2011 at 15:53

2 Answers 2

2

This seems more complicated than it needs to be, but it works. I'm hoping there's a more direct way of doing this...

@staticmethod
def fromFieldHash(h):
 row = MyModel()
 cols = list(row.__table__._columns)
 for k, v in h.iteritems():
 col = find(lambda c: c.key == k, cols)
 # See http://www.sqlalchemy.org/trac/wiki/06Migration#AnImportantExpressionLanguageGotcha
 if col is not None:
 prop = row.__mapper__._columntoproperty[col].key
 setattr(row, prop, v)
 return row

The find method I'm using is from Cleanest Python find-in-list function.

answered Jun 29, 2011 at 16:04

1 Comment

It seems Mapper.columntoproperty has been protected (prefixed with _), so this'll require some tweaking. Prolly a call to Mapper.get_property_by_column() instead.
0

If one would like __init__ to handle both attributes and columns, though having a dedicated classmethod factory seems like a cleaner approach, the following implementation could be used as an abstract base:

from sqlalchemy import inspect
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
def _create_col_lookup(mapper):
 return {c.name: k for k, c in mapper.columns.items()}
class ColBase(Base):
 __abstract__ = True
 def __init__(self, *args, **kwargs):
 # Create a lookup of column name -> attr key
 ctoa = _create_col_lookup(inspect(self).mapper)
 # Process intersecting keys
 for k in ctoa.keys() & kwargs.keys():
 setattr(self, ctoa[k], kwargs.pop(k))
 super().__init__(*args, **kwargs)

Using the above the following asserts pass:

class Foo(ColBase):
 __tablename__ = 'foo'
 id = Column(Integer, primary_key=True)
 bar = Column('Baz 1')
f = Foo(**{'Baz 1': 1})
assert f.bar == 1
f = Foo(**{'bar': 1})
assert f.bar == 1
answered Oct 4, 2018 at 11:13

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.