You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 timezone
    
    赋值逻辑调整为:
    notification.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 07:24:03