Many-to-one relationship in SQLAlchemy

二次信任 提交于 2020-01-05 07:16:53

问题


This is a beginner-level question.

I have a catalog of mtypes:

mtype_id name
       1 'mtype1'
       2 'mtype2'
[etc]

and a catalog of Objects, which must have an associated mtype:

obj_id mtype_id name
     1        1 'obj1'
     2        1 'obj2'
     3        2 'obj3'
[etc]

I am trying to do this in SQLAlchemy by creating the following schemas:

mtypes_table = Table('mtypes', metadata,
 Column('mtype_id', Integer, primary_key=True),
 Column('name', String(50), nullable=False, unique=True),
)

objs_table = Table('objects', metadata,
 Column('obj_id', Integer, primary_key=True),
 Column('mtype_id', None, ForeignKey('mtypes.mtype_id')),
 Column('name', String(50), nullable=False, unique=True),
)

mapper(MType, mtypes_table)
mapper(MyObject, objs_table, 
 properties={'mtype':Relationship(MType, backref='objs', cascade="all, delete-orphan")}
)

When I try to add a simple element like:

mtype1 = MType('mtype1')
obj1 = MyObject('obj1')
obj1.mtype=mtype1
session.add(obj1)

I get the error:

AttributeError: 'NoneType' object has no attribute 'cascade_iterator'

Any ideas?


回答1:


Have you tried:

Column('mtype_id', ForeignKey('mtypes.mtype_id')),

instead of:

Column('mtype_id', None, ForeignKey('mtypes.mtype_id')),

See also: http://www.sqlalchemy.org/docs/05/reference/sqlalchemy/schema.html#sqlalchemy.schema.ForeignKey




回答2:


I was able to run the code you have shown above so I guess the problem was removed when you simplified it for the purpose of this question. Is that correct?

You didn't show a traceback so only some general tips can be given.

In SQLAlchemy (at least in 0.5.8 and above) there are only two objects with "cascade_iterator" attribute: sqlalchemy.orm.mapper.Mapper and sqlalchemy.orm.interfaces.MapperProperty.

Since you didn't get sqlalchemy.orm.exc.UnmappedClassError exception (all mappers are right where they should be) my wild guess is that some internal sqlalchemy code gets None somewhere where it should get a MapperProperty instance instead.

Put something like this just before session.add() call that causes the exception:

from sqlalchemy.orm import class_mapper
from sqlalchemy.orm.interfaces import MapperProperty

props = [p for p in class_mapper(MyObject).iterate_properties]
test = [isinstance(p, MapperProperty) for p in props]
invalid_prop = None
if False in test:
    invalid_prop = props[test.index(False)]

and then use your favourite method (print, python -m, pdb.set_trace(), ...) to check the value of invalid_prop. It's likely that for some reason it won't be None and there lies your culprit.

If type(invalid_prop) is a sqlalchemy.orm.properties.RelationshipProperty then you have introduced a bug in mapper configuration (for relation named invalid_prop.key). Otherwise it's hard to tell without more information.



来源:https://stackoverflow.com/questions/2952010/many-to-one-relationship-in-sqlalchemy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!