我在models.py中有这样的东西
class ZipCode(models.Model):
zip = models.CharField(max_length=20)
cities = City.objects.filter(zip=self).distinct()
class City(models.Model):
name = models.CharField(max_length=50)
slug = models.CharField(max_length=50)
state = models.ForeignKey(State)
zip = models.ManyToManyField(ZipCode)
当我这样做时,我得到:
NameError: name 'City' is not defined
这是因为申报的顺序很重要吗?如果是这样,我怎么能这样做,因为我安排这个,看起来我会得到一个NameError。
感谢。
答案 0 :(得分:6)
除订单问题外,这是错误的:
cities = City.objects.filter(zip=self).distinct()
它不在方法内部,因此“self”也将是未定义的。它只在类创建时执行一次(即首次导入模块时),因此创建的属性将是一个类属性,并且对所有实例具有相同的值。您可能正在寻找的是:
@property
def cities(self):
return City.objects.filter(zip=self).distinct()
因为这是在方法内部,在访问之前不会执行,因此排序问题将不再是问题。正如ozan所指出的,这是Django反向关系已经免费提供给你的重复:
a_zip_code.city_set.all()
您可以使用related_name来调用它:
zip = models.ManyToManyField(ZipCode, related_name='cities')
...
a_zip_code.cities.all()
所以我认为您最初询问的订购问题甚至与您的情况无关。如果是,其他人已经指出在ForeignKey和ManyToManyField声明中使用带引号的字符串来绕过它。
答案 1 :(得分:5)
当你引用了之后定义的类时,你可以使用这个技巧:
attribute = models.ForeignKey('ClassDefinedAfterThis')
答案 2 :(得分:3)
我曾经担心订单...因为我认为下面的模型只能参考上面的模型。但后来意识到你可以做一个
models.ForeignKey('appName.modelName')
一切都很好。
答案 3 :(得分:2)
是的,订单确实很重要,但你的例子对我来说并不合适。我认为你应该只使用外键来实现多对一关系:
cities = models.ForeignKey(City)
This has the details与django模型的多对一关系。
编辑:
在评论中我指出,欧洲的城市可能有几个相同邮政编码的城市。如果您在这里寻找多对多关系,您应该使用:
cities = models.ManyToManyField(City)
Django's documentation中对此进行了描述。关键是,这些示例中的任何一个都比示例中使用的更清晰。
答案 4 :(得分:2)
是的,订单确实很重要,正如其他人所说的那样。
尽管如此,遇到这个问题几乎总是表明你做错了什么。
在这种情况下你的声明:
cities = City.objects.filter(zip=self).distinct()
...同时是redundant和不良做法。您可以通过在视图中引用该邮政编码的city_set来找到与邮政编码相关的城市(即不在您的模型中!)。因此,如果zip是ZipCode的一个实例,你可以这样做:
cities = zip.city_set.all()
如果您真的想将其称为'cities'而不是'city_set',则可以在m2m声明中使用related_name参数。
答案 5 :(得分:0)
订单在Python中很重要。 This thread可能与您的问题相关。另外,您可能希望在邮政编码类中使用唯一的外键。