声明的顺序在models.py(Django / Python)中是否重要?

时间:2009-04-28 01:39:50

标签: django django-models

我在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。

感谢。

6 个答案:

答案 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可能与您的问题相关。另外,您可能希望在邮政编码类中使用唯一的外键。