同一对模型的一对一和多对一关系

时间:2018-07-20 22:44:49

标签: django django-models

我有一个Profile模型和Photo模型。每个个人资料都有照片(一对多关系)和个人资料照片(一对一关系)。当我尝试在Django上执行此操作时,收到错误NameError: name 'Photo' is not defined ,因为我在定义模型之前就引用了该模型。

class Profile(models.Model):
    name = models.CharField(max_length=50, primary_key=True, blank=False)
    profile_photo = models.OneToOneField(
        Photo,
        null=True,
        on_delete=models.SET_NULL
    )

class Photo(models.Model):
    profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
    photo = models.ImageField(primary_key=True, upload_to='photos/')

一种可能的解决方案是在Photo上使用布尔值字段来指定是否为个人资料照片,但是我认为这样效率不高,因为我不得不查询个人资料的所有照片并循环查找个人资料照片。有更好的解决方案吗?

1 个答案:

答案 0 :(得分:1)

问题不是创建两个关系的事实。尽管它可能会引起一些麻烦(因此最好定义related_name等),但问题是您在构造类之前先引用它

实际上,Python从顶部到底部读取文件。在文件中,您定义了一个类Profile并引用了Photo,但此时还没有名为Photo的变量(无论该类是否无关紧要,在最少适用于Python)。

您可以改为使用字符串文字来解决此问题,Django稍后将在加载所有模型时自行进行链接。所以你可以这样写:

class Profile(models.Model):
    name = models.CharField(max_length=50, primary_key=True, blank=False)
    profile_photo = models.OneToOneField(
        'Photo',
        null=True,
        on_delete=models.SET_NULL
    )

话虽这么说,但我仍然不清楚为什么要定义两个关系:Django自动添加反向关系,因此在profile = ...类中未指定Photo的情况下,Django会自动添加这样的关系profile关系。然后,这将通过使用JOIN(并以“反向”查询数据库)来工作。除非两个关系是两种将两种模型组合的不同方法,否则最好使用一种关系,因为这样可以避免重复数据