Django点击按钮更新Notification模型viewed_at空值为当前时间问题排查
代码存在的问题及修复方案
核心错误点
- 路由参数缺失:你定义的
viewed-notification路由要求传入notification_id参数,但模板中调用{% url 'users:viewed-notification' %}时没有传递该参数,会直接触发路由匹配错误,请求根本无法到达mark_as_read视图。 - 请求类型与取值不匹配:你用
<a>标签发起的是GET请求,但mark_as_read视图中从request.POST取next参数,GET请求不存在POST数据,会触发KeyError导致视图报错。 - HTML语法错误:模板中的
<tr>、<td>、<a>、<span>标签均存在嵌套错误、未正确闭合的问题,会导致浏览器渲染异常,链接可能无法正常触发。 - 时区与安全、异常处理缺陷:直接使用
datetime.datetime.now()赋值,若项目开启了时区配置(USE_TZ = True)会导致时间存储错误;同时直接用get()查询通知,传入不存在的ID会直接抛出500错误,也没有校验当前用户是否为通知所属人,存在越权操作的安全漏洞。
修正后的代码
1. 模板部分
<table class="table table-theme-3 text-left"> <tbody> {% for item in unviewed_list %} <tr> <td>{{ item.message }}</td> <td>{{ item.created_at}}</td> <td> <span class="badge badge-error"> <a class="button button--success button--sm" href="{% url 'users:viewed-notification' item.id %}?next={{ request.path }}"> See it </a> </span> </td> </tr> {% endfor %} </tbody> </table>
2. mark_as_read视图部分
from django.shortcuts import get_object_or_404, redirect from django.utils import timezone def mark_as_read(request, notification_id): # 同时校验权限、防止查询不存在的通知 notification = get_object_or_404(Notification, pk=notification_id, user=request.user) notification.viewed_at = timezone.now() notification.save() # 优先取GET参数的next,默认跳转回通知列表页 next_url = request.GET.get('next', '/notifications/') return redirect(next_url)
3. 可选性能优化
可以把更新操作改成单句SQL执行,减少数据库请求次数:
Notification.objects.filter(pk=notification_id, user=request.user).update(viewed_at=timezone.now())
内容的提问来源于stack exchange,提问作者Ken Ist
相关产品推荐
相关产品推荐

