SqlAlchemy进行了多对多的数据建模

时间:2011-11-22 05:55:22

标签: many-to-many sqlalchemy data-modeling

请帮我在SQLAlchemy中对此进行建模。用户可以创建问题。一个问题可以有多种选择(例如,是,不,以后,可能,不知道,下一年,不适用)。我在问题和选择之间创建了一个映射器。如何在SQLAlchemy中建模响应?

question_choices = Table('question_choices', Base.metadata,
    Column('id', Integer, primary_key=True),
    Column('question_id', Integer, ForeignKey('questions.id')),
    Column('choice_id', Integer, ForeignKey('choices.id'))
    )

class Choice(Base):
    __tablename__ = 'choices'
    id = Column(Integer, primary_key=True)
    value = Column(String(30), nullable=False)

class Question(Base):
    __tablename__ = 'questions'
    id = Column(Integer, primary_key=True)
    title   = Column(String(100))
    created = Column(DateTime)

    choices = relationship('Choice', secondary=question_choices)

class questionResponse(Base):
    """A friend's response to a question"""
    __tablename__ = 'question_responses'
    id = Column(Integer, primary_key=True)
    question_id = Column(Integer, ForeignKey('questions.id'))
    choice_id = Column(Integer, ForeignKey('choices.id'))
    user_id = Column(Integer, ForeignKey('users.id'))
    created = Column(DateTime)

questionResponse模型未规范化。 Question_id和listing_id重复出现。我在mapper表中没有关系。我希望能够计算给定问题的答案。

1 个答案:

答案 0 :(得分:1)

QuestionResponse的映射器已经相当不错了,但它不会限制未配置选项的答案:因此,如果不允许LATER,请回答问题Will you marry me? ,数据库不限制此。

一个解决方案就是要向QuestionResponse添加两列外键约束:

class QuestionResponse(Base):
    """A friend's response to a question"""
    __tablename__ = 'question_responses'
    id = Column(Integer, primary_key=True)
    question_id = Column(Integer, ForeignKey('questions.id'))
    choice_id = Column(Integer, ForeignKey('choices.id'))
    # ...
    __table_args__ = (
            ForeignKeyConstraint(['question_id', 'choice_id'], ['question_choices.question_id', 'question_choices.choice_id']),
            )

替代(更规范化的数据库模型)是仅将FK定义为question_choices.id

class QuestionResponse(Base):
    """A friend's response to a question"""
    __tablename__ = 'question_responses'
    id = Column(Integer, primary_key=True)
    question_choice_id = Column(Integer, ForeignKey('question_choices.id'))

edit-1 :在这种情况下,您可以在下面定义的Question和QuestionResponse之间建立关系,这也会为您提供计数:

class Question(Base):
    # ....
    answers = relationship("QuestionResponse", 
        primaryjoin="Question.id==question_choices.c.question_id",
        secondary=question_choices,
        secondaryjoin="question_choices.c.id==QuestionResponse.question_choice_id",
        backref="question",
        )

在任何情况下,您都可以在UniqueConstraint列的question_choices表格中添加(question_id, choice_id)


现在,为了计算回复,您可以在QuestionQuestionResponse之间添加关系并返回len(answers),也可以在Question上创建基于查询的属性:

class Question(Base):
    # ...
    answer_count = column_property(
                select([func.count(QuestionResponse.__table__.c.id)]).
                where(question_choices.c.question_id==id).
                where(question_choices.c.id==QuestionResponse.__table__.c.question_choice_id)
            )