如何在Django中筛选is_active=False且无可用密码的未激活用户
解决Django中查询未激活且无可用密码用户的问题
嘿,这个问题我之前也碰到过!Django的has_usable_password()是模型实例方法,没法直接用在QuerySet的filter()里——因为filter()是直接转换成数据库查询语句的,而方法是Python层面的逻辑。不过别担心,我们可以通过它的底层实现逻辑来模拟这个查询。
方法一:直接根据密码字段特征过滤
先搞清楚has_usable_password()的判断逻辑:当用户的password字段是'!'、None或者空字符串''时,这个方法会返回False(这也是Django调用set_unusable_password()或者创建无密码用户时的默认处理)。所以我们可以直接针对这些特征写查询:
from django.db.models import Q # 获取未激活且无可用密码的用户 inactive_no_password_users = User.objects.filter( is_active=False, Q(password__exact='!') | Q(password__isnull=True) | Q(password__exact='') )
方法二:用注解(annotate)标记可用状态
如果想让查询逻辑更清晰,也可以先通过annotate()给QuerySet添加一个标记字段,再过滤:
from django.db.models import BooleanField, Case, When, Value users = User.objects.annotate( has_usable_pw=Case( When(password__exact='!', then=Value(False)), When(password__isnull=True, then=Value(False)), When(password__exact='', then=Value(False)), default=Value(True), output_field=BooleanField() ) ).filter(is_active=False, has_usable_pw=False)
最佳实践:封装成自定义Manager方法
如果这个查询你会经常用到,建议把它封装到自定义的UserManager里,这样调用起来更简洁:
from django.contrib.auth.models import AbstractUser, BaseUserManager from django.db.models import Q class UserManager(BaseUserManager): # 保留默认的create_user、create_superuser等方法 def create_user(self, username, email=None, password=None, **extra_fields): # 你的实现... pass # 添加自定义查询方法 def get_inactive_no_password_users(self): return self.filter( is_active=False, Q(password__exact='!') | Q(password__isnull=True) | Q(password__exact='') ) class User(AbstractUser): # 指定自定义Manager objects = UserManager()
之后调用的时候就可以直接写:
inactive_users = User.objects.get_inactive_no_password_users()
这样不管是代码可读性还是复用性都更好~
内容的提问来源于stack exchange,提问作者Balakrishnan
相关产品推荐
相关产品推荐

