Django通知功能异常:新建工单无法显示对应提示
问题描述
在Django项目中开发了通知功能,其余功能正常,但模板无法根据操作展示对应消息:新建工单时,始终显示“工单已更新”,而非预期的“新工单已分配给你”。
模板代码
<div class="dropdown-content" id="myDropdown"> {% if notifications %} {% for notification in notifications %} {% if notification.notification_type == 'created' %} <a href="#">{{notification.ticket.name}}: A new ticket has been assigned to you.</a> {% else %} <a href="#">{{notification.ticket.name}}: The ticket has been updated.</a> {% endif %} {% endfor %} {% else %} <a href="#">No new notifications</a> {% endif %} </div>
通知模型(models.py)
class Notification(models.Model): OPTIONS = ( ('created', 'created'), ('updated', 'updated'), ) recipient = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, related_name='notifications') ticket = models.ForeignKey(Ticket, on_delete=models.SET_NULL, null=True, related_name='notifications') message = models.TextField() notification_type = models.CharField(choices=OPTIONS, max_length=15, null=True) is_read = models.BooleanField(default=False) created = models.DateTimeField(auto_now_add=True)
通知信号(signals.py)
@receiver(post_save, sender=Ticket) def create_notification(sender, instance, created, **kwargs): if created: notification_type = 'created' else: notification_type = 'updated' assignees = instance.assignee.all() for assignee in assignees: Notification.objects.create(recipient=assignee, notification_type=notification_type)
创建工单视图(views.py)
@login_required def createTicket(request): form = TicketForm() categories = Category.objects.all() users = CustomUser.objects.all() if request.method == 'POST': category_name = request.POST.get('category') category, created = Category.objects.get_or_create(name=category_name) # Retrieve the project object that the ticket should be connected with project_id = request.POST.get('project') project = Project.objects.get(id=project_id) # Retrieve the list of selected users from the form assignee_ids = request.POST.getlist('assignee') assignee = CustomUser.objects.filter(id__in=assignee_ids) ticket = Ticket.objects.create( host = request.user, category=category, project=project, name=request.POST.get('name'), status=request.POST.get('status'), priority=request.POST.get('priority'), type=request.POST.get('type'), description=request.POST.get('description'), ) # Add the selected users to the ticket ticket.assignee.set(assignee) ticket.save() return redirect('ticket', pk=ticket.id) context = {'form': form, 'categories': categories, 'users': users} return render(request, 'tickets/ticket_form.html', context)
问题排查
- 二次触发post_save信号:创建工单时,
ticket.assignee.set(assignee)后手动调用ticket.save(),会再次触发Ticket的post_save信号,此时created=False,生成updated类型通知。而第一次创建ticket时,assignee尚未设置,信号中instance.assignee.all()为空,不会创建通知,最终用户看到的是第二次生成的updated通知。 - 通知未关联工单:创建Notification时未指定
ticket=instance,导致通知与工单无关联,模板中{{notification.ticket.name}}可能出现异常。 - 必填字段未赋值:Notification模型的
message字段为必填项,但创建时未传入该参数,会引发数据库保存错误。
修复方案
1. 修改创建工单视图(views.py)
移除ticket.assignee.set(assignee)后的ticket.save(),因为set()方法会自动保存多对多关联关系,无需手动调用save():
@login_required def createTicket(request): form = TicketForm() categories = Category.objects.all() users = CustomUser.objects.all() if request.method == 'POST': category_name = request.POST.get('category') category, created = Category.objects.get_or_create(name=category_name) project_id = request.POST.get('project') project = Project.objects.get(id=project_id) assignee_ids = request.POST.getlist('assignee') assignee = CustomUser.objects.filter(id__in=assignee_ids) ticket = Ticket.objects.create( host = request.user, category=category, project=project, name=request.POST.get('name'), status=request.POST.get('status'), priority=request.POST.get('priority'), type=request.POST.get('type'), description=request.POST.get('description'), ) ticket.assignee.set(assignee) # 移除多余的ticket.save() return redirect('ticket', pk=ticket.id) context = {'form': form, 'categories': categories, 'users': users} return render(request, 'tickets/ticket_form.html', context)
2. 修改通知信号(signals.py)
补充工单关联和message字段赋值:
@receiver(post_save, sender=Ticket) def create_notification(sender, instance, created, **kwargs): if created: notification_type = 'created' message = f"A new ticket has been assigned to you." else: notification_type = 'updated' message = f"The ticket has been updated." assignees = instance.assignee.all() for assignee in assignees: Notification.objects.create( recipient=assignee, ticket=instance, # 关联工单 notification_type=notification_type, message=message # 赋值必填字段 )
3. 可选:模板消息本地化(中文)
将模板中的英文消息替换为中文:
<div class="dropdown-content" id="myDropdown"> {% if notifications %} {% for notification in notifications %} {% if notification.notification_type == 'created' %} <a href="#">{{notification.ticket.name}}: 新工单已分配给你。</a> {% else %} <a href="#">{{notification.ticket.name}}: 工单已更新。</a> {% endif %} {% endfor %} {% else %} <a href="#">暂无新通知</a> {% endif %} </div>
内容的提问来源于stack exchange,提问作者mdaw11
相关产品推荐
相关产品推荐

