SqlAlchemy много ко многим данным моделирования - PullRequest
0 голосов
/ 22 ноября 2011

Пожалуйста, помогите мне смоделировать это в 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 и list_id повторяются.У меня нет отношений в таблице сопоставления.Я хочу иметь возможность подсчитать ответы на заданный вопрос.

1 Ответ

1 голос
/ 22 ноября 2011

Ваш маппер для 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).


Теперь для подсчета ответов вы либо добавляете связь между Question и QuestionResponse и возвращаете 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)
            )
...