Django中如何避免重复过滤软删除用户?QuerySet优化咨询
解决Django软删除用户重复过滤的方案
在Django里实现软删除后重复写过滤条件确实麻烦,下面几个方案能帮你彻底解决这个问题,完全符合Django的最佳实践:
1. 给User模型自定义管理器,默认过滤活跃用户
直接给你的User模型替换默认管理器,让User.objects默认只返回is_active=True的用户,同时保留一个管理器用来查询所有用户(包括软删除的)。
代码示例:
from django.contrib.auth.models import AbstractUser, BaseUserManager from django.db import models class ActiveUserManager(BaseUserManager): def get_queryset(self): # 默认只返回活跃用户 return super().get_queryset().filter(is_active=True) class User(AbstractUser): # 你的自定义字段(如果有的话) # 默认管理器:只查活跃用户 objects = ActiveUserManager() # 备用管理器:查所有用户(包括软删除的) all_users = BaseUserManager()
这样用User.objects.all()就自动排除软删除用户,需要查软删除的用户时,用User.all_users.filter(is_active=False)即可。
2. 给关联模型(Item/Comment)自定义管理器,自动过滤关联的活跃用户
对于和User关联的模型(比如Item、Comment),同样可以自定义管理器,让默认查询自动过滤掉关联用户已软删除的记录。
方式一:每个模型单独定义管理器
class ActiveItemQuerySet(models.QuerySet): def include_inactive_users(self): # 提供一个方法,用来取消过滤,查询所有记录 return self.all() class ItemManager(models.Manager): def get_queryset(self): # 默认过滤关联用户活跃的记录 return ActiveItemQuerySet(self.model, using=self._db).filter(user__is_active=True) class Item(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) # 其他字段 objects = ItemManager() # Comment模型同理 class ActiveCommentQuerySet(models.QuerySet): def include_inactive_users(self): return self.all() class CommentManager(models.Manager): def get_queryset(self): return ActiveCommentQuerySet(self.model, using=self._db).filter(user__is_active=True) class Comment(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) # 其他字段 objects = CommentManager()
使用时:
Item.objects.all():自动返回关联用户活跃的条目Item.objects.include_inactive_users():返回所有条目(包括关联用户已软删除的)
方式二:通用管理器,避免重复代码
如果有多个关联模型,可以封装一个通用的管理器,减少重复代码:
class ActiveRelatedQuerySet(models.QuerySet): def get_queryset(self): return super().get_queryset().filter(user__is_active=True) def active_related_manager(): return models.Manager.from_queryset(ActiveRelatedQuerySet)()
然后在关联模型中直接使用:
class Item(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) objects = active_related_manager() all_objects = models.Manager() # 备用管理器,查所有记录 class Comment(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) objects = active_related_manager() all_objects = models.Manager()
3. 进阶:用QuerySet链式调用实现灵活过滤
如果需要更灵活的过滤逻辑,可以定义基础QuerySet,让所有模型继承,通过链式调用切换过滤状态:
class BaseQuerySet(models.QuerySet): def exclude_inactive_users(self): return self.filter(user__is_active=True) class ItemManager(models.Manager): def get_queryset(self): return BaseQuerySet(self.model, using=self._db) class Item(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) objects = ItemManager()
使用时:
- 默认查所有:
Item.objects.all() - 过滤活跃用户关联的记录:
Item.objects.exclude_inactive_users()
这种方式适合需要频繁切换过滤状态的场景。
内容的提问来源于stack exchange,提问作者aroooo
相关产品推荐
相关产品推荐

