如何使用Django Rest框架在单个请求中反序列化多个文件和表单数据?

2024-09-29 19:24:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我想用一些基本表单数据+一个或多个上传文件来取消搜索表单

如果我发送以下请求(使用Postman作为Python请求代码生成)

import requests

url = "http://127.0.0.1:8000/forms/test/"

payload = {
'customer_id': '123456789',
'customer_name': 'Billy Bob'}
files = [
  ('files', open('/C:/tmp/aaaaa.csv','rb')),
  ('files', open('/C:/tmp/bbbbb.csv','rb'))
]
headers= {}

response = requests.request("POST", url, headers=headers, data = payload, files = files)

print(response.text.encode('utf8'))

代码返回以下响应(我希望它会保存文件)

{
    "files": [
        "This field is required."
    ]
}

模型

from datetime import datetime
from django.db import models

class Mtfar(models.Model):
    date = models.DateTimeField(auto_now_add=True)
    customer_id = models.IntegerField()
    customer_name = models.CharField(max_length=254)

class MtfarFile(models.Model):
    file = models.FileField(blank=False, null=False)
    mtfar = models.ForeignKey(Mtfar, related_name='files', on_delete=models.CASCADE)

序列化程序

from rest_framework import serializers
from .models import Mtfar, MtfarFile

class MtfarFileSerializer(serializers.ModelSerializer):
    class Meta:
        model = MtfarFile
        fields = ['file']

class MtfarSerializer(serializers.ModelSerializer):

    files = MtfarFileSerializer(many=True)

    class Meta:
        model = Mtfar
        fields = ['customer_ptid', 'customer_name', 'files']

看法

from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.decorators import api_view, parser_classes
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status

from .serializers import MtfarSerializer, MtfarFileSerializer

@api_view(['POST'])
@parser_classes([MultiPartParser])
def post_generic_form(request):

    data = request.data
    
    filelist = []
    for f in request.FILES.getlist('files'):
        filelist.append({
            'file': f
        })
    data.setlist('files', filelist)

    serializer = MtfarSerializer(data=data)

    if serializer.is_valid():
        serializer.save()
        return Response(status=status.HTTP_201_CREATED)
    else:
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Tags: namefromimportrestdatamodelsrequeststatus
1条回答
网友
1楼 · 发布于 2024-09-29 19:24:01

您需要将QueryDict对象转换为{}以支持嵌套序列化,因为DRF以不同的方式解析{}(Ref: ^{} method (DRF source code)

@api_view(['POST'])
@parser_classes([MultiPartParser])
def post_generic_form(request):
    dict_data = {
        **request.data.dict(),
        **{"files": [{"file": file} for file in request.FILES.getlist('files')]}
    }
    serializer = MtfarSerializer(data=dict_data)

    if serializer.is_valid():
        serializer.save()
        return Response(status=status.HTTP_201_CREATED)
    else:
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

相关问题 更多 >

    热门问题