基于Django开发自定义消息应用:视图与模板实现咨询
Django 用户间消息发送实现指南
看起来你已经搭好了核心的模型和表单基础,接下来咱们一步步把视图和模板补全,实现用户发送消息、查看消息的功能。先从调整表单开始——因为sender字段不需要用户手动选择,应该自动关联当前登录用户,所以先改下你的表单:
1. 调整表单(forms.py)
from django import forms from .models import Message class MessageForm(forms.ModelForm): class Meta: model = Message fields = ['receiver', 'message_file'] # 移除sender,后续在视图中自动设置
2. 实现视图(views.py)
咱们需要三个核心视图:发送消息、查看收件箱、标记消息为已读(实用功能)。记得加上登录验证,确保只有登录用户才能操作:
from django.shortcuts import render, redirect, get_object_or_404 from django.contrib.auth.decorators import login_required from .models import Message from .forms import MessageForm # 发送消息视图 @login_required def send_message(request): if request.method == 'POST': form = MessageForm(request.POST, request.FILES) if form.is_valid(): message = form.save(commit=False) message.sender = request.user # 自动绑定当前登录用户为发送者 message.save() form.save_m2m() # 多对多字段需手动保存关联关系 return redirect('inbox') # 发送成功后跳转到收件箱 else: form = MessageForm() # 默认排除当前用户,避免给自己发消息 form.fields['receiver'].queryset = form.fields['receiver'].queryset.exclude(id=request.user.id) return render(request, 'messages/send_message.html', {'form': form}) # 收件箱视图 @login_required def inbox(request): # 获取当前用户收到的所有消息,按时间倒序排列(最新的在前) messages = Message.objects.filter(receiver=request.user).order_by('-timestamp') return render(request, 'messages/inbox.html', {'messages': messages}) # 标记消息为已读视图 @login_required def mark_as_read(request, message_id): message = get_object_or_404(Message, id=message_id, receiver=request.user) message.unread = False message.save() return redirect('inbox')
几个关键细节:
- 因为
receiver是多对多字段,form.save(commit=False)后必须调用form.save_m2m()来保存用户关联 - 发送表单默认排除当前用户,避免误操作给自己发消息
- 收件箱按时间倒序排列,让用户优先看到最新消息
3. 编写模板
先在应用目录下创建templates/messages文件夹,然后创建两个核心模板:
发送消息模板(send_message.html)
{% extends 'base.html' %} <!-- 替换成你自己的基础模板 --> {% block content %} <h2>发送消息</h2> <form method="post" enctype="multipart/form-data"> {% csrf_token %} {{ form.as_p }} <button type="submit">发送</button> </form> {% endblock %}
⚠️ 必须加上enctype="multipart/form-data",否则无法正常上传文件。
收件箱模板(inbox.html)
{% extends 'base.html' %} {% block content %} <h2>收件箱</h2> {% if messages %} <ul style="list-style: none; padding: 0;"> {% for message in messages %} <li style="margin-bottom: 15px; padding: 12px; border: 1px solid #eee; {% if message.unread %}background-color: #f8f9fa;{% endif %}"> <p><strong>发送者:</strong> {{ message.sender.username }}</p> <p><strong>发送时间:</strong> {{ message.timestamp|date:"Y-m-d H:i" }}</p> {% if message.unread %} <span style="color: #dc3545; font-size: 0.9em;">未读</span> <a href="{% url 'mark_as_read' message.id %}" style="margin-left: 10px; font-size: 0.9em;">标记为已读</a> {% else %} <span style="color: #28a745; font-size: 0.9em;">已读</span> {% endif %} <p style="margin-top: 8px;"> <a href="{{ message.message_file.url }}" download>下载附件</a> </p> </li> {% endfor %} </ul> {% else %} <p>暂无消息,快去给朋友发一条吧 😊</p> {% endif %} <a href="{% url 'send_message' %}">发送新消息</a> {% endblock %}
这个模板会根据unread字段显示不同的背景色和状态,同时提供附件下载和标记已读的功能,用户体验更友好。
4. 配置URL(urls.py)
在应用的urls.py中添加以下路由配置:
from django.urls import path from . import views urlpatterns = [ path('send/', views.send_message, name='send_message'), path('inbox/', views.inbox, name='inbox'), path('mark-read/<int:message_id>/', views.mark_as_read, name='mark_as_read'), ]
记得把这个应用的URL包含到项目的主urls.py中。
额外优化建议
- 可以添加已发送消息列表视图,过滤
Message.objects.filter(sender=request.user)即可实现 - 在表单中添加文件格式验证,比如只允许PDF、图片等类型:在
MessageForm中添加clean_message_file方法做校验 - 考虑添加消息删除功能,注意多对多关系下的删除逻辑(比如删除消息时是否移除所有接收者的关联)
内容的提问来源于stack exchange,提问作者szatrio
相关产品推荐
相关产品推荐

