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

Django3.1+Vue3通过POST API上传图片时图片字段为空,如何解决?

问题描述

我正在开发一个以Django 3.1为后端、Vue 3为前端的项目,刚接触Django仍在学习阶段,不确定当前实现是否正确。

我创建了包含用户邮箱和图片字段的模型:

class UsedBike(models.Model):
    sellerEmail = models.CharField(max_length=255)
    image = models.ImageField(upload_to='uploads/', blank=True, null=True)

    class Meta:
        ordering = ('sellerEmail', )

    def __str__(self):
        return self.sellerEmail

    def get_image(self):
        if self.image:
            return 'http://127.0.0.1:8000' + self.image.url
        return ''

序列化器代码:

class UsedBikeSerializer(serializers.ModelSerializer):
    class Meta:
        model = UsedBike
        fields = (
            "id",
            "sellerEmail",
            "get_image",
        )

视图保存函数:

@api_view(['POST'])
def sellBike(request):
    serializer = UsedBikeSerializer(data=request.data)
    if serializer.is_valid():
        serializer.save()
    return Response(serializer.data)

前端Vue的请求代码:

submitData() {
    const formData = {
        sellerEmail: this.sellerEmail,
        image: this.productImage
    }
    axios
        .post("/api/v1/sell-bike/", formData)
        .then(response => {
            console.log(response)
        }).catch(error => {
            console.log(error)
        })
},

模板控件:

<input type="text" v-model="sellerEmail">
<input type="file" accept="image/png, image/jpeg" id="imageInput" v-on:change="onFileChange()">
<button @click="submitData">Upload</button>

文件选择方法:

onFileChange(e) {
    let imageInput = document.getElementById("imageInput")
    this.productImage = imageInput.files[0]
},

发送请求后,Django终端返回"POST /api/v1/sell-bike/ HTTP/1.1" 200 55,但打印request.data得到{'sellerEmail': 'test@email.com', 'image': {}},数据库中邮箱已保存,但image字段为空。


解决方案

前端修改:用FormData传递文件

浏览器上传文件必须使用multipart/form-data编码,普通JSON对象无法传递文件,需将数据包装为FormData实例:

submitData() {
    const formData = new FormData();
    formData.append('sellerEmail', this.sellerEmail);
    if (this.productImage) {
        formData.append('image', this.productImage);
    }
    axios.post("/api/v1/sell-bike/", formData, {
        headers: {
            'Content-Type': 'multipart/form-data'
        }
    })
    .then(response => {
        console.log(response)
    }).catch(error => {
        console.log(error)
    })
},

后端修改1:序列化器添加image字段

当前序列化器未包含image字段,无法处理上传的文件。需添加该字段,并将自定义方法get_image标记为SerializerMethodField:

from rest_framework import serializers
from .models import UsedBike

class UsedBikeSerializer(serializers.ModelSerializer):
    get_image = serializers.SerializerMethodField()

    class Meta:
        model = UsedBike
        fields = (
            "id",
            "sellerEmail",
            "image",  # 新增字段用于接收上传文件
            "get_image",
        )

    def get_image(self, obj):
        if obj.image:
            return 'http://127.0.0.1:8000' + obj.image.url
        return ''

后端修改2:完善视图错误反馈

在视图中返回验证错误信息,方便调试,并使用正确的状态码:

from rest_framework.decorators import api_view
from rest_framework.response import Response
from .serializers import UsedBikeSerializer

@api_view(['POST'])
def sellBike(request):
    serializer = UsedBikeSerializer(data=request.data)
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=201)  # 创建成功返回201状态码
    return Response(serializer.errors, status=400)  # 验证失败返回错误详情

额外配置:媒体文件路径设置

在settings.py中配置媒体文件的存储路径和访问URL:

MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'

在项目根urls.py中添加媒体文件路由:

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

urlpatterns = [
    # 你的其他URL配置
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

配置完成后,上传的图片会存储在media/uploads/目录下,可通过http://127.0.0.1:8000/media/uploads/xxx.jpg访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 04:05:15