使用ManyToManyField并确保DatabaseIntegrity

时间:2013-12-12 11:06:20

标签: django django-orm

我有两个模特老师和一个学生。我还有两个模型,一个课程和一个课程,其中课程是实际主题,课程用于划分学生。我想创建以下关系。

A teacher teaches a specific lesson in a specific class e.g Mike teaches python in C3

A student attends a class with a specific lesson e.g George is taking Python in C3

所以最终

George is Mike's student in python in C3

我使用中间模型在两个模型中使用了许多字段。很多人,因为老师可以有很多课程可以教授很多课程,课程可以让很多老师教授不同的课程(同样适合学生)

所以我做了以下事情:

class Teacher(models.Model):
    teaches = models.ManyToManyField(Class, through=TeacherTeaches)

class TeacherTeaches(models.Model):
    teacher = models.ForeignKey(Teacher)
    class = models.ForeignKey(Class)
    lesson = models.ForeignKey(Lesson)

和学生:

class Student(models.Model):
    attends = models.ManyToManyField(Class, through=StudentAttends)


class StudentAttends(models.Model):
    student = models.ForeignKey(Student)
    class = models.ForeignKey(Class)
    lesson = models.ForeignKey(Lesson)

但我认为这个实现无法做到的是确保同一课不是由两个不同的教师在同一课上讲授的,对吗?因为ForeignKey(我认为)。是否有更好的方法来“设置”我的模型以实现上述行为?我应该“统一”两个中间模型吗?

1 个答案:

答案 0 :(得分:2)

也许您需要从另一个方向接近它以限制多对多关系。一个班级(或房间,因为您不能使用关键字class作为标识符)只能有一个课程和一个教师,所以:

class Room(Model):
    teacher = ForeignKey(Teacher)
    lesson = ForeignKey(Lesson)

教师可以教授多个课程,但只能在一个教室中教授,因此可以从Room模型中查询,例如:

Teacher.objects.select_related().values('lesson')

一个学生可以有多个课程,房间和老师,所以没有办法避免多对多的关系,但课程和老师已经在房间里相关,所以创建一个多对多的房间将是最简单的方式。这可以从任何一方完成,因此模型变为:

class Room(Model):
    teacher = ForeignKey(Teacher)
    lesson = ForeignKey(Lesson)
    students = ManyToManyField(Student)

现在,确保教师和课程的独特性就像添加适当的约束一样简单:

class Room(Model):
    teacher = ForeignKey(Teacher)
    lesson = ForeignKey(Lesson)
    students = ManyToManyField(Student)

    class Meta:
        unique_together = ('teacher', 'lesson')