如何在django中定义泛型模型时解决循环依赖

时间:2017-02-12 15:22:11

标签: python django generics django-models

我想定义一个通用模型,可以在任何应用程序中使用。以下是我的通用模型的定义: -

User = settings.AUTH_USER_MODEL
#  This mixin is used to track the user, who has created this object.
class OwnedModel(models.Model):
       owner           = ForeignKey(to=User, null=True, editable=False)

      class Meta:
            abstract    = True

#   AreaOrVillage extending this model, will also get owner field, which
#   refer to User.
class AreaOrVillage(OwnedModel):

    area_village_name   = LocationIdentifierField(name="areaOrVillageName", verbose_name="Area/Village:", blank=False, null=False)
    area_village_code   = LocationCodeField(name="areaOrVillageCode", verbose_name="Area/Village Code", null=True, blank=True)
    zipcode             = ZipCodeField(verbose_name="ZipCode", null=False, blank=False)
    #  It's another model, referred by this model
    tehsil              = models.ForeignKey(to=Tehsil, related_name="areas_or_villages")

    class Meta:
        verbose_name_plural = "Areas/Villages"
        unique_together     = ("tehsil", "areaOrVillageName")
        ordering            = ("tehsil", "areaOrVillageName")
        app_label           = 'location_app'

    def __str__(self):
        text                = self.to_str()
        return "{}{}{}".format(text, ", " if text and self.tehsil else "",
                               self.tehsil.__str__() if self.tehsil else "")

    def to_str(self):
        return "%s" %(self.areaOrVillageName or self.areaOrVillageCode)

现在,在我的django项目中,我已经覆盖了以下默认用户模型(使用了上面定义的通用模型): -

class PSS_User_Type(ModelBase):

    def __new__(cls, name, bases, dictattrs):
        user_type = super(PSS_User_Type, cls).__new__(cls, name, bases, dictattrs)

        OVER_RIDDEN_ATTR    = "is_staff"
        NEW_ATTR            = "is_devteam_member"

        if hasattr(user_type, OVER_RIDDEN_ATTR):
            setattr(user_type, NEW_ATTR,
                    getattr(user_type, OVER_RIDDEN_ATTR))
            delattr(user_type, OVER_RIDDEN_ATTR)

            setattr(user_type, "__getattr__", PSS_User_Type.__getattr__)

        def __getattr__(self, attrname):
            effective_attr = NEW_ATTR if attrname == OVER_RIDDEN_ATTR else attrname
            return super(cls, self).__getattr__(attrname)

        return user_type

class PSS_User(LoggableModel, OwnedModel, ResolvableModelMixin, AbstractUser):

    __metaclass__ = PSS_User_Type

    REQUIRED_FIELDS = ['password', 'first_name', 'last_name',
                        'village', 'gotra']

    #   TODO :- Add phone/mobile no details

    dob = DateField(null=True, blank=True)
    age = SmallIntegerField(null=True, blank=True, validators=[AgeValidator()])
    is_alive = BooleanField(null=False, blank=False, default=True)
    gender  = GenderField(null=False, blank=False)
    user_village = ForeignKey(to=AreaOrVillage, null=False, related_name="gram_vasi")

现在,它引入了循环依赖问题,因为通用模型依赖于用户,为了跟踪他们的创建者,用户定义也使用了泛型模型,因此针对db运行迁移会产生问题

django.db.utils.ProgrammingError: relation "users_pss_user" does not exist

有没有更好的方法来解决这个问题?

提前致谢。

1 个答案:

答案 0 :(得分:0)

to can also be a string中的ForeignKey字段:

  

如果您需要在尚未定义的模型上创建关系,您可以使用模型的名称,而不是模型对象本身

(强调补充)

例如,从您的代码中,您可以执行以下操作:

user_village = ForeignKey(to='AreaOrVillage', null=False, related_name="gram_vasi")

在所有ForeignKey字段中使用该语法,您将避免使用任何循环引用。