Django models.py 循环外键

22 投票
3 回答
11077 浏览
提问于 2025-04-16 03:57

我有一个Django应用,基本上就是一个照片相册。目前我有两个模型:Image(图片)和Album(相册)。简单来说,每个Album都有一个指向Image的外键,用作缩略图,而每个Image也有一个外键,指向它所属的Album。但是,当我尝试使用manage.py syncdbmanage.py sqlall时,系统报错说在models.py中第一个定义的类没有定义。

这是我简化后的models.py:

from django.db import models
import os

class Album(models.Model):
    thumb = models.ForeignKey(Image, null=True, blank=True)

class Image(models.Model):
    image = models.ImageField(upload_to='t_pics/images')
    thumb = models.ImageField(upload_to='t_pics/images/thumbs')
    album = models.ForeignKey(Album)

当我执行manage.py sqlall appname时,出现的错误是:

[...]
 File "/path/to/file/appname/models.py", line 4, in ?
    class Album(models.Model):
  File "/path/to/file/appname/models.py", line 5, in Album
    thumb = models.ForeignKey(Image, null=True, blank=True)
NameError: name 'Image' is not defined

如果我调换models.py中类的顺序,系统会报同样的错误,只不过这次是说'Album'未定义,而不是'Image'未定义。我还尝试过在第一个类中注释掉依赖关系,然后在其他内容成功导入后再取消注释,但这也没有解决问题。我该如何处理才能让它正常工作?我不太想创建一个新的类Thumb,因为它会有很多和Image相同的代码。我也很确定我可以手动将外键添加到数据库,但我希望这个过程干净利落,而不是走捷径。

3 个回答

0

这虽然是个老问题,但我想说的是,我觉得在图片模型中没有必要有这个“专辑”属性。在我看来,这个属性其实并不需要。

13

使用引号可以强制使用懒加载引用:

models.ForeignKey('Image', null=True, blank=True)

另外,ForeignKey.related_name 是个好帮手(可以避免反向引用名称冲突)。

46

其实你并没有真正出现循环引用的问题;问题在于,当你定义Album的时候,Image还没有被定义。你可以通过用字符串来解决这个问题:

class Album(models.model):
  thumb = models.ForeignKey('Image', null=True, blank=True)

不过在这种情况下,你可能想用OneToOneField,而不是外键。(不过你还是得用字符串的那个小技巧)。

撰写回答