Django Views.py中mark_as_read函数写法是否正确?get_object_or_404用法合规吗?
代码规范与优化指正
现有写法的合理性
你当前的get_object_or_404用法功能上完全合法:get_object_or_404支持接收QuerySet实例作为首个入参,你通过filter匹配通知ID、exclude排除已读通知的逻辑可以正常生效,找不到符合条件的通知时会正确返回404响应,不存在语法错误。
可优化的规范调整点
- 过滤逻辑简化:
exclude(viewed_at__isnull=False)等价于正向过滤filter(viewed_at__isnull=True),更符合常规阅读习惯,不需要反向推导排除逻辑。 get_object_or_404写法简化:Django官方更推荐将模型类作为首个入参,后续直接拼接过滤条件,写法更简洁,调整后如下:notification = get_object_or_404(Notification, pk=notification_id, viewed_at__isnull=True)- 时区兼容性优化:如果你的Django项目开启了
USE_TZ = True(默认开启),直接使用datetime.datetime.now()会生成不带时区的本地时间,可能触发时区警告或数据错误,建议替换为Django自带的时区工具:
首先导入依赖:
赋值逻辑调整为:from django.utils import timezonenotification.viewed_at = timezone.now() - 权限逻辑补全:当前代码没有校验通知所属用户,任意用户只要传入正确的通知ID就能将他人的通知标记为已读,存在业务逻辑漏洞,建议在过滤条件中增加用户校验(假设Notification模型存在关联用户的
user字段):notification = get_object_or_404(Notification, pk=notification_id, viewed_at__isnull=True, user=request.user) - 性能优化可选方案:当前逻辑需要先查询一次数据库拿通知实例,再执行save写入数据库,合计两次DB操作。如果不需要触发Notification的
save信号、也不需要用到实例的其他字段,可以直接用update方法实现单次DB操作:from django.http import Http404 from django.utils import timezone def mark_as_read(request, notification_id): updated_count = Notification.objects.filter( pk=notification_id, viewed_at__isnull=True, user=request.user ).update(viewed_at=timezone.now()) if not updated_count: raise Http404 return redirect('users:notification')
内容的提问来源于stack exchange,提问作者Ken Ist
相关产品推荐
相关产品推荐

