使用 Django DRF 和 Celery 在后台任务中上传文件时出现“TemporaryUploadedFile 类型的对象不可 JSON 序列化”

问题描述 投票:0回答:1

这是我的创建功能:

    def create(self,request,*args,**kwargs):
    
        serializer = ArchiveSerializer( data = request.data, context = {"request":request} )
        serializer.is_valid(raise_exception=True)
        filename=serializer.validated_data.pop('file')
        serializer.save()
        id = serializer.validated_data.get("id")
        save_file_in_background.delay(id,filename)
        
        return Response(serializer.data, status=status.HTTP_201_CREATED)

这是tasks.py

from celery import shared_task
from django.core.files.base import ContentFile
from .models import Archive

@shared_task
def save_file_in_background(id,filename):
    try:
        archive = Archive.objects.get(pk=id)

        
        
        if filename:
            archive.file.save(filename, ContentFile(filename))
        

        archive.save()
        
    except Archive.DoesNotExist:
        pass  

但是当尝试添加对象并上传文件时出现此错误: TemporaryUploadedFile 类型的对象不可 JSON 序列化

除了在后台上传文件但出现此错误: “TemporaryUploadedFile 类型的对象不可 JSON 序列化”

django django-rest-framework django-views
1个回答
0
投票

发生错误是因为

TemporaryUploadedFile
(上传的文件)无法直接传递给celery,因为它不是json可序列化的。您在这里可以做的是在创建实例时保存文件并仅传递 ID 以避免序列化。

但我认为你想卸载图像发布任务而不阻塞主要请求-响应周期。

您可以通过首先仅保存基本详细信息(不包括图像)的最小数据并向客户端返回响应来做到这一点。然后将任何所需信息传递给 Celery 任务来处理图像上传。

from rest_framework import status
from rest_framework.response import Response
from .tasks import upload_image_background_task

def create(self, request, *args, **kwargs):
    serializer = ArchiveSerializer(data=request.data, context={"request": request})
    serializer.is_valid(raise_exception=True)

    # initially save the instance without image
    archive_instance = serializer.save(file=None)

    # take the uploaded image file from the request
    uploaded_image = request.FILES.get('file')

    # pass the instance id and the image data to the background task
    upload_image_background_task.delay(archive_instance.id, uploaded_image.read(), 
uploaded_image.name)

    # return response immediately
    return Response(serializer.data, status=status.HTTP_201_CREATED)

在你的tasks.py文件中修改:

@shared_task
def upload_image_background_task(archive_id, image_data, image_name):
    try:
        archive = Archive.objects.get(pk=archive_id)
        
        # save the image file in the background
        archive.file.save(image_name, ContentFile(image_data))
        
        # save the instance to finalize changes
        archive.save()
        
    except Archive.DoesNotExist:
        pass  # handle the case where the instance might not exist
© www.soinside.com 2019 - 2024. All rights reserved.