django 一对一反向查找覆盖

django one to one reverse lookup override

需要一对一反向查询方面的帮助。我的模特:

class User(MarkedAsDeletedMixin):
    fields here

class UserProfile(MarkedAsDeletedMixin):
    user = models.OneToOneField(User)

class MarkedAsDeletedMixin(models.Model):
    marked_as_deleted = models.BooleanField(default=False)

    class Meta:
        abstract = True

    def delete(self, *args, **kwargs):
        self.marked_as_deleted = True
        self.save()

您可以看到我正在覆盖 delete 方法,所以当我这样做时 someuser.userprofile.delete() 我只是将用户配置文件对象标记为已删除。

当我 someuser.userprofile 之后,问题就来了。我得到了用户资料,因为我没有删除用户资料,我只是将其标记为已删除。

为了仅获取未标记为已删除的 userprofile 对象,我需要覆盖 User 的一对一反向查找或对 UserProfile 的管理器进行一些操作。有什么想法吗?

从技术上讲,该记录存在,因此覆盖 user.profile 以隐藏它是没有意义的。这会使代码更难理解。

您可以改为添加方法:

class User(MarkedAsDeletedMixin):
    def get_profile():
        return self.profile if self.profile and not self.profile.marked_as_deleted else None

class UserProfile(MarkedAsDeletedMixin):
    user = models.OneToOneField(User, related_name="profile")

这是一对一关系,主要实体是 User 实例,而不是 UserProfile 实例。换句话说,user 是大多数代码中使用的内容。例如,在视图中,您使用 request.user.

我不确定软删除配置文件在您的应用程序中意味着什么,但让我们假设它不是 public。在那种情况下,我会将其保存在 User:

class User(MarkedAsDeletedMixin):
     is_profile_public = models.BooleanField(default=True)

是的,您可以使用管理器,您只需要修改 get_queryset。最好将它放在 MarkedAsDeletedMixin 的管理器上——它应该被任何子类继承。像这样:

from django.db import models

class MarkedAsDeletedManager(models.Manager):

    use_for_related_fields = True

    def get_queryset(self):
        return self.filter(marked_as_deleted=False)

class MarkedAsDeletedMixin(models.Model):
    marked_as_deleted = models.BooleanField(default=False)
    objects = MarkedAsDeletedManager()

    class Meta:
        abstract = True

    def delete(self, *args, **kwargs):
        self.marked_as_deleted = True
        self.save()