Django - 调用模型save()而不使用“对象”管理器get_queryset

时间:2014-11-25 18:05:44

标签: django django-models

我正在为客户开发一个传统的Django 1.7系统。我之前的程序员用过滤器查询覆盖了成员模型(基本上是用户模型)“对象”属性,该查询删除了“is_deleted”设置为“True”的任何内容。我列出了以下片段:

会员类摘要:

class Member(AbstractUser):
    objects = MemberManager()
    all_objects = models.Manager()

MemberManager类代码段:

class MemberManager(BaseUserManager):
    def get_queryset(self):
        return super(MemberManager, self).get_queryset().filter(is_deleted=False)

现在,当我尝试更新将is_deleted标志设置为“True”的用户时,它将失败。下面是一个示例代码段。请注意我如何使用“all_objects”这是默认的models.Manager(),它返回所有记录。

user = Member.all_objects.get(pk=id) # id of an is_deleted = True record
user.is_deleted = False
user.save()

此代码导致运行此Django查询,但遗憾的是WHERE子句中包含“is_deleted = 0”,这导致它无法找到记录。以下是日志中显示的内容:

  

UPDATE Member [[snip ...]] WHERE(Memberis_deleted = 0 AND Memberid = 6)

有没有办法调用不会使用MemberManager.objects get_queryset过滤器的“save()”?

2 个答案:

答案 0 :(得分:3)

我认为问题源于首先列出MemberManager。正如the documentation所说:

  

请注意,第一个Manager Django遇到(按照模型中定义的顺序)具有特殊状态。 Django将类中定义的第一个Manager解释为“默认”Manager,Django的几个部分将专门用于该模型Manager。因此,在选择默认管理器时要小心谨慎,以避免覆盖get_queryset()导致无法检索您想要使用的对象。

撤销objectsall_objects的顺序可以解决问题。

答案 1 :(得分:2)

我尝试了Kevin Christopher Henry的回答,不幸的是,更改默认管理器搞砸了身份验证代码,需要继承" BaseUserManager"类。解决方案是创建一个"取消删除"使用" all_objects"的成员模型类中的函数在用户保存之前取消删除用户的属性。

class Member(AbstractUser):
    objects = MemberManager() # default manager
    all_objects = models.Manager()

    def undelete(self):
        if self.is_deleted:
            Member.all_objects.filter(id=self.id).update(is_deleted=False)

然后在我的代码中我做了这个:

user = Member.all_objects.get(pk=id)
user.undelete()