Путаница ассоциации SQLAlchemy

У меня есть студенческая база данных в SQLAlchemy со следующими таблицами.

class Marks(Base):
    __table_args__ = {'extend_existing': True}
    __tablename__ = 'marks'
    id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
    mark = Column(Integer, nullable=False, unique=False)
    subject_fk = Column(Integer, ForeignKey('subjects.id'))
    subject = relationship('Subjects', foreign_keys=[locale_fk],uselist=False,
                          backref='marks', innerjoin=False, post_update=False)


class Subjects(Base):
    __table_args__ = {'extend_existing': True}
    __tablename__ = 'subjects'
    id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
    subject = Column(String(10, convert_unicode=True), nullable=False, unique=True)


class StudentIds(Base):
    __table_args__ = {'extend_existing': True}
    __tablename__ = 'student_ids'
    id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
    student_id = Column(String(50, convert_unicode=True), nullable=False,unique=False)


    junctionid = relationship("Junction", cascade='save-update',
                                     backref='student_ids', lazy='select', post_update=True)
    mk=relationship("Marks",secondary=lambda:junction_table)
    marks = association_proxy('mk', 'mark')


class Junction(Base):
    __table_args__ = {'extend_existing': True}
    __tablename__ = "junction_table"

    student_id_fk = Column(Integer, ForeignKey('student_ids.id'), primary_key=True)
    mark_fk = Column(Integer, ForeignKey('marks.id'), primary_key=True)
    mark = relationship('Marks', cascade='save-update', backref='mark_id_mapper', innerjoin=True)

У меня есть данные, заполненные в таблице Student Ids, Marks and Subjects. Теперь мне нужно заполнить соединительную таблицу внешними ключами student_id и mark (оценки, полученные в каждом предметы вставляются в таблицу отметок). Как мне это сделать, я имею в виду, что я могу создать прокси-ассоциацию внутри таблицы идентификаторов учащихся, которая сопоставляется с таблицей отметок, и заполнить ее там?

Я просмотрел эту документацию: http://docs.sqlalchemy.org/en/rel_0_9/orm/extensions/associationproxy.html и я как бы понимаю, что мне нужен этот прокси между student_id и отметками... чтобы я мог запросить student_id.mark для получения отметок. Но как мне получить это в моей таблице Junction?

Может кто-нибудь, пожалуйста, направьте меня?


person Tania    schedule 04.03.2015    source источник


Ответы (1)


Я предлагаю отношение «один ко многим» (один студент — много оценок, http://docs.sqlalchemy.org/en/rel_0_9/orm/basic_relationships.html#one-to-many). Таким образом, вы можете добавить student_id в свою модель Marks и связь с моделью Marks to StudentIds вместо создания модели Junction.

class StudentIds(Base):
    __table_args__ = {'extend_existing': True}
    __tablename__ = 'student_ids'
    id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
    student_id = Column(String(50, convert_unicode=True), nullable=False,unique=False)


    junctionid = relationship("Junction", cascade='save-update',
                                 backref='student_ids', lazy='select', post_update=True)
    marks = relationship("Marks", backref="student")


class Marks(Base):
    __table_args__ = {'extend_existing': True}
    __tablename__ = 'marks'
    id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
    mark = Column(Integer, nullable=False, unique=False)
    subject_fk = Column(Integer, ForeignKey('subjects.id'))
    subject = relationship('Subjects', foreign_keys=[subject_fk],uselist=False,
                      backref='marks', innerjoin=False, post_update=False)
    student_id = Column(Integer, ForeignKey('student_ids.id'))
    student = relationship('StudentIds', foreign_keys=[student_id])


class Subjects(Base):
    __table_args__ = {'extend_existing': True}
    __tablename__ = 'subjects'
    id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
    subject = Column(String(10, convert_unicode=True), nullable=False, unique=True)

Если вы хотите создать отношение «многие ко многим», вам может понадобиться создать таблицу ассоциаций (http://docs.sqlalchemy.org/en/rel_0_9/orm/basic_relationships.html#many-to-многие)

association_table = Table('association', Base.metadata,
    Column('students_id', Integer, ForeignKey('student_ids.id')),
    Column('marks_id', Integer, ForeignKey('marks.id'))
)


class Marks(Base):
    __table_args__ = {'extend_existing': True}
    __tablename__ = 'marks'
    id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
    mark = Column(Integer, nullable=False, unique=False)
    subject_fk = Column(Integer, ForeignKey('subjects.id'))
    subject = relationship('Subjects', foreign_keys=[subject_fk],uselist=False, backref='marks', innerjoin=False, post_update=False)


class Subjects(Base):
    __table_args__ = {'extend_existing': True}
    __tablename__ = 'subjects'
    id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
    subject = Column(String(10, convert_unicode=True), nullable=False, unique=True)


class StudentIds(Base):
   __table_args__ = {'extend_existing': True}
   __tablename__ = 'student_ids'
   id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
   student_id = Column(String(50, convert_unicode=True), nullable=False,unique=False)


   junctionid = relationship("Junction", cascade='save-update',
                                 backref='student_ids', lazy='select', post_update=True)
   marks = relationship("Marks", secondary=association_table)

В любом случае вам не нужна модель Junction для создания связи между учениками и их оценками.

person Timur Osadchiy    schedule 04.03.2015
comment
Но таблица соединений — это место, где я буду собирать всю информацию. Скажем, идентификатор студента, идентификатор отметки, идентификатор субъекта и все внешние ключи в одном месте. После того, как эти три таблицы будут заполнены соответствующей информацией, как мне поместить их в мою существующую соединительную таблицу? Вышеупомянутый дизайн, который вы предлагаете, превосходен, но есть ли способ использовать существующую соединительную таблицу для заполнения информации о внешнем ключе? - person Tania; 04.03.2015
comment
потому что у меня также может появиться новая модель для «студенческого класса». Каждый класс будет иметь список student_id со списком оценок учеников по каждому предмету. В этом случае было бы лучше, если бы у меня была соединительная таблица с составным ключом Student_id и class, за которым следуют внешние ключи предмета и класса. тогда вставки могут быть независимыми, а модель соединения должна содержать консолидированную информацию. В конце концов я должен запрашивать только соединительную таблицу. Есть ли способ сделать это? - person Tania; 04.03.2015
comment
Если вы планируете иметь модель StudentClass, она будет иметь отношение «многие ко многим» со StudentIds, поэтому вы можете использовать подход, который я предложил выше (таблица ассоциаций). Затем вы можете просто добавить StudentClass.id в модель Mark. Таким образом, вы сможете получить список оценок для конкретного ученика или класса или того и другого. Опять же, я бы не советовал использовать эту модель Junction. - person Timur Osadchiy; 04.03.2015
comment
Хорошо. Есть еще одно уточнение. Предположим, мне нужна информация о статусе в каком-то столбце, который называется «проверено», для каждого идентификатора учащегося, отметки и класса. этот проверенный столбец можно поместить в соединительную таблицу. Итак, если я хочу узнать информацию о состоянии любого из вышеперечисленных полей (sid, метки, класс), я могу запросить модель соединения. Можете ли вы предложить какие-либо обходные пути для этого? Кроме того, модель класса моего ученика может быть связана с моими оценками для получения сводных оценок, полученных каждым классом. - person Tania; 04.03.2015
comment
Если я правильно вас понял, каждая оценка по каждому предмету, учащемуся и студенческому классу может быть проверена или нет. Затем Verified является свойством Марка, и вам нужно просто добавить еще один проверенный логический столбец. Когда вам нужно получить список отметок для студента, вы просто запрашиваете модель отметок по StudentIds.id. Если вам нужно получить оценки для определенного класса для конкретного ученика, вы просто запрашиваете модель отметки по StudentIds.id и StudentClass.id. - person Timur Osadchiy; 04.03.2015
comment
Да, все сводится к статусу метки. Учитывая ваш подход, мне нужно иметь поле в таблице меток, но я должен создать связь между меткой и всем остальным. Приступим к вставке. У меня есть информация о субъектах и ​​оценках в моей модели оценок. Мне нужно рассказать, как ученик относится к своей отметке. если появляется новый класс, он становится числом записей studentxmarksxclass, что нарушает простоту таблицы оценок. Вот почему я подумал, что у нас может быть таблица, в которой есть ТОЛЬКО поля внешнего ключа и поля состояния, поэтому Очистка/вставка становится легкой рутиной. - person Tania; 04.03.2015
comment
Я предполагаю, что наша таблица оценок становится вариантом нашей модели соединения.. В которой есть информация о предмете, статусе и оценке в одном месте. Как теперь вставить? Я поставлю student_ids, и в моем классе Mark будет куча информации об оценках по предметам. Нужно ли мне добавлять что-либо student-id.marks.append(), чтобы вставить отметку каждого учащегося? У меня есть CSV-файл с идентификатором студента и оценками, полученными по каждому предмету.. поля: studentid,mark1,mark2,mark3... Теперь, как я могу сказать, что x studentid получил x оценку? И что мне делать с таблицей ассоциаций? :( Я действительно запутался сейчас. Пожалуйста, уточните - person Tania; 04.03.2015
comment
Если вы используете первый подход, предложенный в моем ответе, вам не нужно будет создавать ассоциативную таблицу для каждой связи. Вы просто добавляете связь с StudentIds, StudentClass и Subject в модель Mark. Вот так: student_id = Column(Integer, ForeignKey('student_ids.id')) student = отношения('StudentIds', Foreign_keys=[student_id]) - person Timur Osadchiy; 04.03.2015
comment
Извините, забыл принять, поставив +1 к вашему ответу. Вы, конечно, очень помогли .. Одно маленькое сомнение. как мне получить информацию student_id в моей таблице оценок?? Это означает, когда и как я могу вставить в него информацию о внешнем ключе student.id? При вставке в таблицу student_id я знаю, какие оценки получил студент (через файл csv). В то время? У вас есть способ вставить их, используя мою модель Junction (в моем initializedb)? - person Tania; 04.03.2015
comment
В яблочко! Сначала вы создаете объект Student. Затем вы создаете объект Mark с этим студентом. - person Timur Osadchiy; 04.03.2015