【问题标题】:Does order of declaration matter in models.py (Django / Python)?models.py(Django / Python)中的声明顺序是否重要?
【发布时间】:2010-10-22 05:00:51
【问题描述】:

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

谢谢。

【问题讨论】:

    标签: django django-models


    【解决方案1】:

    除了订单问题,这是错误的:

    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 声明中使用带引号的字符串来绕过它。

    【讨论】:

      【解决方案2】:

      当你有对之后定义的类的引用时,你可以使用这个技巧:

      attribute = models.ForeignKey('ClassDefinedAfterThis')
      

      【讨论】:

      • 这行得通吗? city = 'City'.objects.filter(zip=self).distinct()
      【解决方案3】:

      是的,正如其他人所说,顺序确实很重要。

      不过,遇到这个问题几乎总是表明你做错了什么。

      在这种情况下,您的声明:

      cities = City.objects.filter(zip=self).distinct()
      

      ... 既是 redundant 也是不好的做法。您可以通过在您的视图中(即不在您的模型中!)引用该邮政编码的 city_set 来找到与该邮政编码相关的城市。所以如果 zip 是 ZipCode 的一个实例,你会这样做:

      cities = zip.city_set.all()
      

      如果您真的想将其称为“城市”而不是“城市集”,您可以在 m2m 声明中使用相关名称参数。

      【讨论】:

        【解决方案4】:

        我曾经担心订单...因为我认为我下面的模型只能参考上面的模型。但后来意识到你可以做一个

        models.ForeignKey('appName.modelName')
        

        一切都很好。

        【讨论】:

          【解决方案5】:

          是的,顺序确实很重要,但你的例子对我来说并不合适。我认为您应该只为多对一关系使用外键:

          cities = models.ForeignKey(City)
          

          This has the details 与 django 模型建立多对一关系。

          编辑:

          在 cmets 中向我指出,欧洲的城市可能有多个城市在同一个邮政编码中。如果您在这里寻找多对多关系,您应该使用:

          cities = models.ManyToManyField(City)
          

          这在Django's documentation 中有描述。关键是,这两个示例中的任何一个都比示例中使用的要清楚得多。

          【讨论】:

          • 嗨 Shane,您的建议似乎暗示一个邮政编码只能与一个城市相关联,但我认为邮政编码可以属于多个城市,一个城市可以有多个邮政编码。不是这样吗?
          • 不,你可以有多对一的关系,但我不熟悉你在这里使用的语法。根据我上面提供的链接:“要定义多对一关系,请使用 ForeignKey()”
          • 多对一和多对多是两种不同的关系,Shane。在这种情况下,多对多可能更合适,因为单个邮政编码可能代表多个城市(国际思考)。但这不是重点。在两个方向上声明二元关系既不是一个好主意,也是多余的。
          • 好的,如果他想要多对多关系,他应该使用 models.ManyToManyField(City) - 我会将其添加到我的答案中。
          【解决方案6】:

          Python 中的顺序很重要。 This thread 可能与您的问题有关。此外,为了您的使用,您可能希望在邮政编码类中使用唯一的外键。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-03-23
            • 2019-12-11
            • 1970-01-01
            • 2016-10-05
            • 1970-01-01
            • 2014-03-12
            • 1970-01-01
            • 2012-08-30
            相关资源
            最近更新 更多