SQLAlchemy关系填充外键字段

时间:2015-02-24 11:19:56

标签: python sqlalchemy

我有以下表格及其各自的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'类。

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

最后这是我的表格看起来

已登记:

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

生:

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

现在,如何让学生ID进入注册表作为外键?

我有这样的信息:哪个学生作为.csv文件注册到哪个科目。 mycsv:name,subject,name1,subject1,name2,subject2

我应该有像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字段?

1 个答案:

答案 0 :(得分:1)

您的1对多注册表应具有学生ID和主题的复合主键。假设您希望将主题保留为ENUM(适用于较小的主题列表,否则您应将其移至单独的表),您的表应如下所示:

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)

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