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

如何使用Django Rest Framework为Django聊天应用添加附件发送功能

Django聊天应用附件发送功能实现方案

一、后端Django侧改造

  • 修改消息模型
    找到你的Message模型类,新增附件存储字段,普通文本消息该字段留空即可:
from django.db import models
from django.contrib.auth.models import User

class Message(models.Model):
    sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sender')
    receiver = models.ForeignKey(User, on_delete=models.CASCADE, related_name='receiver')
    message = models.TextField(blank=True) # 允许文本为空,支持纯附件消息
    # 新增附件字段
    attachment = models.FileField(upload_to='chat_attachments/%Y/%m/', blank=True, null=True)
    timestamp = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ('timestamp',)

修改后执行python manage.py makemigrations和python manage.py migrate同步数据库。

  • 配置媒体文件访问路径
    在settings.py中添加配置:
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'

在项目根路由urls.py中添加媒体路由映射:

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # 保留原有路由
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
  • 修改序列化器
    调整消息序列化器,添加附件字段的序列化支持:
from rest_framework import serializers
from .models import Message

class MessageSerializer(serializers.ModelSerializer):
    class Meta:
        model = Message
        fields = ('id', 'sender', 'receiver', 'message', 'attachment', 'timestamp')
  • 修改消息发送视图
    原有视图仅支持JSON格式提交,需要调整为支持multipart/form-data格式,接收上传的文件:
# 消息创建视图示例
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Message
from .serializers import MessageSerializer

class MessageCreateView(APIView):
    def post(self, request):
        # 从表单数据中取字段,文件从request.FILES取
        serializer = MessageSerializer(data={
            'sender': request.data.get('sender'),
            'receiver': request.data.get('receiver'),
            'message': request.data.get('message', ''),
            'attachment': request.FILES.get('attachment')
        })
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=201)
        return Response(serializer.errors, status=400)

二、前端侧改造

  • 修改HTML结构
    在聊天输入区域新增文件选择控件,同时修改表单编码类型:
<form id="chat-box" enctype="multipart/form-data">
  <input type="text" id="id_message" placeholder="输入消息...">
  <!-- 新增文件选择按钮 -->
  <button type="button" id="attach-btn">📎 附件</button>
  <input type="file" id="id_attachment" style="display: none;" accept="image/*,.pdf,.doc,.docx,.txt">
  <button type="submit">发送</button>
</form>

<!-- 消息模板需要新增附件渲染位置,示例: -->
<template id="text-box-template">
  <div class="message {align}">
    <div class="sender">{sender}</div>
    <div class="content">
      <div class="text">{message}</div>
      <div class="attachment"></div>
    </div>
  </div>
</template>

在原有script中添加附件按钮触发逻辑:

$(function () {
  // 原有逻辑保留,新增下面的附件按钮点击事件
  $('#attach-btn').click(function() {
    $('#id_attachment').click();
  });
})
  • 修改消息发送函数
    原有发送函数使用JSON格式提交,调整为使用FormData传递数据和文件:
function send(sender, receiver, message, attachment = null) {
    let formData = new FormData();
    formData.append('sender', sender);
    formData.append('receiver', receiver);
    formData.append('message', message);
    if (attachment) {
        formData.append('attachment', attachment);
    }

    $.ajax({
        url: '/api/messages',
        type: 'POST',
        data: formData,
        contentType: false,
        processData: false,
        success: function (data) {
            console.log(data);
            var box = $('#text-box-template').html().replace('{sender}', "You");
            box = box.replace('{align}', 'right');
            box = box.replace('{message}', message);
            // 渲染附件
            let $box = $(box);
            if (data.attachment) {
                renderAttachment(data.attachment, $box.find('.attachment'));
            }
            $('#board').append($box);
            // 发送后清空文件选择
            $('#id_attachment').val('');
            scrolltoend();
        }
    })
}
  • 修改表单提交逻辑
    调整提交事件,获取选中的附件传入send函数:
$('#chat-box').on('submit', function (event) {
  event.preventDefault();
  var message = $('#id_message');
  var attachment = $('#id_attachment')[0].files[0];
  send('{{ request.user.username }}', '{{ receiver.username }}', message.val(), attachment);
  message.val('');
})
  • 修改消息接收函数,新增附件渲染逻辑
    先写一个通用的附件渲染函数,再在接收逻辑中调用:
// 通用附件渲染函数
function renderAttachment(attachmentUrl, $container) {
    // 判断是不是图片
    const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
    const ext = attachmentUrl.split('.').pop().toLowerCase();
    if (imageExts.includes(ext)) {
        $container.html(`<img src="${attachmentUrl}" style="max-width: 200px; max-height: 200px; border-radius: 4px;">`);
    } else {
        const fileName = attachmentUrl.split('/').pop();
        $container.html(`<a href="${attachmentUrl}" target="_blank" download>📎 下载附件:${fileName}</a>`);
    }
}

// 修改后的receive函数
function receive() {
    $.get('/api/messages/' + sender_id + '/' + receiver_id, function (data) {
        console.log(data);
        if (data.length !== 0) {
            for (var i = 0; i < data.length; i++) {
                var box = $('#text-box-template').html().replace('{sender}', data[i].sender);
                box = box.replace('{align}', 'left blue lighten-5');
                box = box.replace('{message}', data[i].message);
                var $box = $(box);
                // 渲染附件
                if (data[i].attachment) {
                    renderAttachment(data[i].attachment, $box.find('.attachment'));
                }
                $('#board').append($box);
                scrolltoend();
            }
        }
    })
}

三、补充注意事项

  • 后端要添加文件校验:限制文件大小(比如最大10M)、禁止上传exe、js等可执行文件,避免安全风险
  • 大文件传输建议采用分片上传逻辑,避免请求超时
  • 可以添加上传进度条提升用户体验

内容的提问来源于stack exchange,提问作者HarshitaJaya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 06:06:00