两个表中的Django对称多对多

时间:2019-04-02 07:57:22

标签: django django-models

我发现在Django中令人沮丧的一件事是在定义多对多关系时看似必需的不对称性。我教Django,我真的很想找到描述和教Django中多对多关系的“最优雅”的方法。

我的一位学生在制作多对多模型时使用了将类名作为字符串输入的技术。这样一来,她就可以避免使用像related-name这样不太直观的技巧。这是她模型的简化版本- key PersonCourse是字符串,而不是类名。

class Person(models.Model):
    email = models.CharField(max_length=128, unique=True)
    courses = models.ManyToManyField('Course', through='Membership')

class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    course = models.ForeignKey(Course, on_delete=models.CASCADE)

class Course(models.Model):
    title = models.CharField(max_length=128, unique=True)
    members = models.ManyToManyField('Person', through='Membership')

但是,虽然这对我来说很漂亮,但我担心自己搞砸了。我已经做了一些基本的测试,并没有看到这种模型定义风格的缺点,但是我担心我搞砸了一些我什至不了解的东西。因此,我提出一个问题,“这张图片有什么问题?”

1 个答案:

答案 0 :(得分:2)

使用字符串定义关系字段并没有什么不同寻常或有争议的地方;这是有据可查的。但这与使关系对称无关。

我不清楚您的学生为什么两次定义了这种关系。似乎没有必要,就像使用显式的穿透表一样。您的定义完全等同于这个简单得多的定义:

class Person(models.Model):
    email = models.CharField(max_length=128, unique=True)
    courses = models.ManyToManyField('Course', related_name='members')

class Course(models.Model):
    title = models.CharField(max_length=128, unique=True)

请注意,您无需在Course上定义任何内容,也不需要显式的穿透表-即使没有额外的字段,也可以禁用某些功能,例如嵌入式管理表单。给定一个Course对象,您可以执行my_course.members.all()来获得与您的版本相同的成员。