【问题标题】:Flask-Sqlalchemy 3 way many to many relationshipFlask-Sqlalchemy 3 方式多对多关系
【发布时间】:2014-01-10 00:41:20
【问题描述】:

我正在尝试为事件和事件回复创建数据库...

对于每个活动,都应该有可能的食物供 rsvp 选择

当用户回复时,为他们创建的 rsvp 模型应该包含他们目前选择的食物。

这是我目前所拥有的:

event_meals = db.Table('event_meals',
                       db.Column('meal_id', db.Integer, db.ForeignKey('meal.id')),
                       db.Column('event_id', db.Integer, db.ForeignKey('event.id')))

rsvp_meals = db.Table('rsvp_meals',
                      db.Column('meal_id', db.Integer, db.ForeignKey('meal.id')),
                      db.Column('rsvp_id', db.Integer, db.ForeignKey('rsvp.id')))

class Event(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(256), unique=True)
    date = db.Column(db.String(128))
    photo = db.Column(db.String(256))
    info = db.Column(db.String(1024))
    meals = db.relationship('Meal', secondary='event_meals',
                            backref=db.backref('meals', lazy='dynamic'))

    def __repr__(self):
        return self.title


class Rsvp(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128))
    price = db.Column(db.String(64))
    meals = db.relationship('Meal', secondary='rsvp_meals',
                            backref=db.backref('meals', lazy='dynamic'))

    def __repr__(self):
        return self.name


class Meal(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(128))
    price = db.Column(db.Integer)
    qty = db.Column(db.Integer)

    def __repr__(self):
        return self.title

不出所料,这会报错:

sqlalchemy.exc.ArgumentError:在关系“Rsvp.meals”上创建反向引用“meals”时出错:映射器“Mapper|Meal|meal”上存在该名称的属性

谁能帮我完成这项工作?!非常感谢您的帮助!

【问题讨论】:

    标签: python-2.7 flask flask-sqlalchemy


    【解决方案1】:

    backref 是应该用来暴露 related 模型上的多对多关系的名称。在您的情况下,您是说EventRsvp 模型都应该作为meals 模型上的meals 属性公开。换句话说,当我有一个Meal 并且我想查看谁有回复时,我应该访问Meal 实例上的meals 属性。但是,您还声明,如果我想查看餐点与 Events 相关联,我应该访问餐点的 meals 属性......这就是 SQLAlchemy 抛出错误的原因。

    您最可能的意思是在Meals 上公开rsvpsevents

    class Event(db.Model):
        # ... snip ...
        meals = db.relationship('Meal', secondary='event_meals',
                                backref=db.backref('events', lazy='dynamic'))
    
    # ... snip ...    
    
    class Rsvp(db.Model):
        # ... snip ...
        meals = db.relationship('Meal', secondary='rsvp_meals',
                                backref=db.backref('rsvps', lazy='dynamic'))
    

    然后,对于任何Meal 实例,您可以查询其Events 和RSVPs:

    for rsvp in Meal.query.get(meal_id).rsvps:
        print rsvp.name
    

    要注意的关键是 SQLAlchemy 是一个非常 DRY(不要重复自己)的框架。如果您发现自己必须在同一字段声明的不同部分之间保持名称同步,那么您可能错过了一种更简单的处理方式。

    【讨论】:

    • 你摇滚肖恩!很好的解释,而且效果很好。谢谢大佬!
    • 这真的是最好的方法吗?为什么不制作一个典型的 3way 接线表?
    • @applewood - 这可能不是最好的方法 - 但问题是关于为什么 OP 有问题。 event_idmeal_idrsvp_id 的表格可能更有意义(取决于用例)。
    • 如果餐本身重复出现,上述情况是否有效。例如,第 1 餐出现在事件 1 和事件 2 中,rsvp 1 和 rsvp 2 吃了第 1 餐。
    • 我试过上面的命令:AttributeError: type object 'Rating' has no attribute 'get'。我如何定义get?
    猜你喜欢
    • 2016-06-15
    • 2021-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-03
    • 2018-09-07
    • 2019-01-12
    • 1970-01-01
    相关资源
    最近更新 更多