SQLAlchemy 关系填充外键字段

SQLAlchemy relationships populating foreign key fields

我有以下 tables 及其各自的 sqlalchemy 类:

class Enrolled(Base):
    __tablename__ = 'enrolled'
    id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
    student_fk = Column(Integer, ForeignKey('students.id'))
    student = relationship('Students', foreign_keys=[device_fk], uselist=False,backref="enrolled", innerjoin=False, post_update=False)
    subject = Column(String(5, convert_unicode=True), nullable=False)

//__init__ for id and subject is here.

class Students(Base):
    __tablename__ = 'students'
    id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
    name = Column(String(50, convert_unicode=True), nullable=False)   
//init for name is here

students 和 enrolled 之间的关系是一对多的。即一个学生可以注册超过 1 个科目。

现在,我知道要在 'Enrolled' 中插入几个主题,在 'Students' 中插入几个名字 类。

DBSession.add(Enrolled(subject="maths"))

最后这就是我 table 的样子

已注册:

+----+------------+---------+
| id | student_fk | subject |         
+----+------------+---------+
|  1 |            | Maths   |
|  2 |            | Physics | 
|  3 |            |  Art    | 
+----+------------+---------+

学生:

+----+------+
| id | name |  
+----+------+
|  1 | Jim  | 
|  2 | Bob  |  
|  3 | Cara |  
+----+------+

现在,如何让学生 ID 作为外键进入 Enrolled table?

我有以下信息:哪个学生注册了哪个科目作为 .csv 文件。 mycsv: 名称、主题、名称 1、主题 1、名称 2、主题 2

我是否应该有一本像 dict {jim:maths,Bob:Art,Cara:Physics} 这样的手动字典,然后映射成

query=Enrolled(subject="maths")

for k, v in dict.items():
    if subject in v:
        list.append(k)
for i in list:
    query.student=DBSession.query(Students).filter(name=i).first()
    DBSession.add(query)

请帮助..如何正确填充 student_fk 字段?

您的一对多注册 table 应该在学生 ID 和主题上有复合主键。假设您希望将主题保留为 ENUM(它适用于较小的主题列表,否则您应该将其移动到单独的 table),您的 table 应该看起来像:

subjects = [ 'Maths', 'Physics', 'Art', ]

class Student(Base):
  __tablename__ = 'Student'
  student_id = Column(Integer, primary_key=True, autoincrement=True)
  name = Column(String(50, convert_unicode=True), nullable=False)

class StudentEnrollment(Base):
  __tablename__ = 'StudentEnrollment'
  student_id = Column(Integer, ForeignKey('Student.student_id', ondelete='CASCADE'), primary_key=True)
  subject = Column(Enum(*subjects), primary_key=True)
  student = relationship("Student",   primaryjoin='StudentEnrollment.student_id==Student.student_id', uselist=True, backref="enrollments")

这将导致:

root@localhost [inDB]> show create table Student\G
*************************** 1. row ***************************
       Table: Student
Create Table: CREATE TABLE `Student` (
  `student_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`student_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

root@localhost [inDB]> show create table StudentEnrollment\G
*************************** 1. row ***************************
       Table: StudentEnrollment
Create Table: CREATE TABLE `StudentEnrollment` (
  `student_id` int(11) NOT NULL,
  `subject` enum('Maths','Physics','Art') NOT NULL,
  PRIMARY KEY (`student_id`,`subject`),
  CONSTRAINT `StudentEnrollment_ibfk_1` FOREIGN KEY (`student_id`) REFERENCES `Student` (`student_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

然后为用户 Jim 插入几个注册:

student = Student(name='Jim')
session.add(student)
session.flush()
for enr in ('Maths', 'Physics', 'Art'):
  session.add(StudentEnrollment(student_id=student.student_id, subject=enr))     
session.flush()
session.commit()

这将导致:

root@localhost [inDB]> select * from Student;
+------------+------+
| student_id | name |
+------------+------+
|          3 | Jim  |
+------------+------+
1 row in set (0.00 sec)

root@localhost [inDB]> select * from StudentEnrollment;
+------------+---------+
| student_id | subject |
+------------+---------+
|          3 | Maths   |
|          3 | Physics |
|          3 | Art     |
+------------+---------+
3 rows in set (0.00 sec)

这是一个非常基本的例子,有两个 table。更好的选择是将注册规范化为单独的 table 并使用关联代理模式,请参阅 http://docs.sqlalchemy.org/en/rel_0_9/orm/extensions/associationproxy.html