Flask帮助理解多对多关系中的primaryjoin / secondaryjoin

时间:2014-03-01 05:23:58

标签: python sqlalchemy flask relationship

我有用户和列表类,我正在尝试创建多对多关系,以便用户可以拥有许多喜欢的列表,并且任何列表都可以被许多用户收藏。

我一直在使用this作为参考,但这是我的第一个多对多关系,所以任何帮助都会受到赞赏。

  

InvalidRequestError:一个或多个映射器无法初始化 - 不能   继续初始化其他映射器。最初的例外是:   无法确定primaryjoin条件的关系方向   'favorites_table.user_id =:user_id_1',关系   User.favorites。确保引用Column对象具有   ForeignKey存在,或者是ForeignKeyConstraint的其他部分   他们的父表,或指定foreign_keys参数   关系。

models.py

favorites_table = db.Table('favorites_table',
  db.Column('user_id', db.Integer, db.ForeignKey('listing.id')),
  db.Column('listing_id', db.Integer, db.ForeignKey('user.id'))
)

class User(db.Model):
  id = db.Column(db.Integer, primary_key = True)
  listings = db.relationship('Listing', backref = 'manager', lazy = 'dynamic')
  favorites  = db.relationship('Listing',
    secondary=favorites_table,
    primaryjoin = ('favorites_table.c.user_id == id'), 
    secondaryjoin = ('favorites_table.c.listing_id == id'),
    backref = db.backref('user', lazy = 'dynamic'),
    lazy = 'dynamic')

  def favorite_listing(self, listing):
    if not self.is_favorite(listing):
    self.favorites.append(listing)
    return self

  def unfavorite_listing(self, listing):
    if self.is_favorite(listing):
    self.favorites.remove(listing)
    return self

  def is_favorite(self, listing):
    return self.favorites.filter(favorites_table.c.listing_id == listing.id).count() > 0


class Listing(db.Model):
  id = db.Column(db.Integer, primary_key = True)
  user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

1 个答案:

答案 0 :(得分:3)

由于您的模型已指定所有必需ForeignKey,因此sqlachemy足够聪明,可以找出primaryjoinsecondaryjoin本身的参数。所以这应该工作得很好:

favorites  = db.relationship('Listing',
    secondary = favorites_table,
    # primaryjoin = 'favorites_table.c.user_id == User.id',
    # secondaryjoin = 'favorites_table.c.listing_id == Listing.id',
    backref = db.backref('users', lazy = 'dynamic'),
    lazy = 'dynamic',
    )

如果您真的希望明确,可以取消注释上面的两行,以获得完全相同的结果。请注意,我在指定的每个id列之前添加了模型名称。

请注意,favorites_table关系表列user_id指向Listing.id listing_id -> User.id,而它看起来应该是另一种方式。