SQLAlchemy Relationship Error: object has no attri

2019-05-11 04:36发布

问题:

I used sqlautocode to generate my model and all the relationships. I'm trying to do a simple query like

obj = session.query(Venue).filter(Venue.symbol=="CARNEGIE_HALL").one()

For some reason I keep getting this error message:

File "/usr/lib64/python2.6/site-packages/sqlalchemy/orm/relationships.py", line 331, in _annotate_present_fks
          secondarycols = util.column_set(self.secondary.c)
      AttributeError: 'Event' object has no attribute 'c'

If I comment out the relationship definitions, then the query above works. The relationship definitions generated by sqlautocode look right to me but I'm new to SqlAlchemy. I'm not sure how to fix this. I tried changing from relation() to relationship() but I still get the same error.

Using sqlalchemy 0.8.2 and sqlautocode 0.6.

Note there's a many-to-one relation between Event and Event_Type and a many-to-one between Event and Venue.

model.py

DeclarativeBase = declarative_base()
metadata = DeclarativeBase.metadata
metadata.bind = engine

Event = Table(u'Event', metadata,
    Column(u'id', INTEGER(), primary_key=True, nullable=False),
    Column(u'venue_id', INTEGER(), ForeignKey('Venue.id'), nullable=False),
    Column(u'event_type_id', INTEGER(), ForeignKey('Event_Type.id'), nullable=False),
)

Venue = Table(u'Venue', metadata,
    Column(u'id', INTEGER(), ForeignKey('Obj.id'), primary_key=True, nullable=False),
    Column(u'venue_type_id', INTEGER(), ForeignKey('Venue_Type.id'), nullable=False),
    Column(u'name', VARCHAR(length=100), nullable=False),
    Column(u'symbol', VARCHAR(length=50), nullable=False),
)

class Event(DeclarativeBase):
    __table__ = Event


    #relation definitions
    Event_Type = relation('EventType', primaryjoin='Event.event_type_id==EventType.id')
    Venue = relation('Venue', primaryjoin='Event.venue_id==Venue.id')


class EventType(DeclarativeBase):
    __tablename__ = 'Event_Type'

    __table_args__ = {}

    #column definitions
    code = Column(u'code', VARCHAR(length=50), nullable=False)
    description = Column(u'description', VARCHAR(length=250))
    id = Column(u'id', INTEGER(), primary_key=True, nullable=False)
    name = Column(u'name', VARCHAR(length=100), nullable=False)

    #relation definitions
    Venues = relation('Venue', primaryjoin='EventType.id==Event.event_type_id', secondary=Event, secondaryjoin='Event.venue_id==Venue.id')


class Venue(DeclarativeBase):
    __table__ = Venue


    #relation definitions
    Event_Types = relation('EventType', primaryjoin='Venue.id==Event.venue_id', secondary=Event, secondaryjoin='Event.event_type_id==EventType.id')

Error log

  mod_wsgi (pid=10861): Exception occurred processing WSGI script '/home/uname/web/html/foo/app/main.py'.
  Traceback (most recent call last):
    File "/home/uname/web/html/foo/app/main.py", line 208, in application
      return callback(environ, start_response)
    File "/home/uname/web/html/foo/app/main.py", line 68, in monitor
      obj = session.query(Venue).filter(Venue.symbol=="CARNEGIE_HALL").one()
    File "/usr/lib64/python2.6/site-packages/sqlalchemy/orm/session.py", line 1106, in query
      return self._query_cls(entities, self, **kwargs)
    File "/usr/lib64/python2.6/site-packages/sqlalchemy/orm/query.py", line 115, in __init__
      self._set_entities(entities)
    File "/usr/lib64/python2.6/site-packages/sqlalchemy/orm/query.py", line 124, in _set_entities
      self._set_entity_selectables(self._entities)
    File "/usr/lib64/python2.6/site-packages/sqlalchemy/orm/query.py", line 157, in _set_entity_selectables
      ent.setup_entity(*d[entity])
    File "/usr/lib64/python2.6/site-packages/sqlalchemy/orm/query.py", line 2728, in setup_entity
      self._with_polymorphic = ext_info.with_polymorphic_mappers
    File "/usr/lib64/python2.6/site-packages/sqlalchemy/util/langhelpers.py", line 614, in __get__
      obj.__dict__[self.__name__] = result = self.fget(obj)
    File "/usr/lib64/python2.6/site-packages/sqlalchemy/orm/mapper.py", line 1426, in _with_polymorphic_mappers
      configure_mappers()
    File "/usr/lib64/python2.6/site-packages/sqlalchemy/orm/mapper.py", line 2121, in configure_mappers
      mapper._post_configure_properties()
    File "/usr/lib64/python2.6/site-packages/sqlalchemy/orm/mapper.py", line 1243, in _post_configure_properties
      prop.init()
    File "/usr/lib64/python2.6/site-packages/sqlalchemy/orm/interfaces.py", line 231, in init
      self.do_init()
    File "/usr/lib64/python2.6/site-packages/sqlalchemy/orm/properties.py", line 1028, in do_init
      self._setup_join_conditions()
    File "/usr/lib64/python2.6/site-packages/sqlalchemy/orm/properties.py", line 1102, in _setup_join_conditions
      can_be_synced_fn=self._columns_are_mapped
    File "/usr/lib64/python2.6/site-packages/sqlalchemy/orm/relationships.py", line 115, in __init__
      self._annotate_fks()
    File "/usr/lib64/python2.6/site-packages/sqlalchemy/orm/relationships.py", line 311, in _annotate_fks
      self._annotate_present_fks()
    File "/usr/lib64/python2.6/site-packages/sqlalchemy/orm/relationships.py", line 331, in _annotate_present_fks
      secondarycols = util.column_set(self.secondary.c)
  AttributeError: 'Event' object has no attribute 'c'

回答1:

you can't say this:

Venues = relation('Venue', primaryjoin='EventType.id==Event.event_type_id', secondary=Event, secondaryjoin='Event.venue_id==Venue.id')

you'd need to say this:

Venues = relation('Venue', primaryjoin='EventType.id==Event.event_type_id', secondary=Event.__table__, secondaryjoin='Event.venue_id==Venue.id')

"secondary" expects only a Table object, not a mapped class.

Also note that SQLAlchemy recommends the association object pattern, rather than making fancy "secondary" setups, to keep this kind of thing more straightforward.