Django模型查询过滤时如何简化多通知标志的冗余判断逻辑
简化实现方案
你不需要编写大量重复的if判断分支,利用Django ORM支持动态传参的特性,配合字段白名单校验,就可以把冗余的分支逻辑压缩到几行,同时避免安全风险。
核心实现
首先维护一份合法通知字段的白名单,从根源上避免前端传入非法字段(比如敏感的is_superuser、password等字段)导致的查询异常或者安全问题:
# 所有允许作为查询条件的通知配置字段都放在这个集合里 ALLOWED_NOTIFICATION_FLAGS = { "send_to_all", "send_to_me", "send_to_friends", "another_send_flag", # 后续新增通知开关,只要在这里补充对应模型字段名即可 }
之后重写send_notifications函数,通过字典解包的方式动态构造filter查询条件:
def send_notifications(flag): # 校验传入字段合法性 if flag not in ALLOWED_NOTIFICATION_FLAGS: # 非法字段可以直接返回空查询集终止流程,也可以根据业务需求抛出错误 return User.objects.none() # 动态构造查询条件,效果和你之前逐行写的filter判断完全一致 users_to_send = User.objects.filter(**{flag: True}) # 后续执行通知发送逻辑即可
注意事项
- 你当前视图层的传参逻辑有问题:现在写的
send_notifications(request.data.get('send_to_all', False))传入的是字段对应的布尔值,不是字段名标识,需要调整传参逻辑:前端传入当前触发的通知类型对应的字段名字符串,视图层取到该字符串后传入函数即可。 - 白名单校验是必须环节,绝对不能直接将前端传入的未校验字符串直接作为字段名传入ORM查询,否则会存在数据泄露风险。
- 如果后续需要支持同时按多个通知标志筛选用户,只要把合法的字段和对应值拼接到查询字典中,再统一解包传给filter即可,示例:
def send_notifications(flag_list): query_params = {} for flag in flag_list: if flag in ALLOWED_NOTIFICATION_FLAGS: query_params[flag] = True users_to_send = User.objects.filter(**query_params)
内容的提问来源于stack exchange,提问作者Hvitis
相关产品推荐
相关产品推荐

