Django Rest Framework:将图像分配给上传文件夹中的模型字段
Django Rest Framework: Assign image to model field from uploaded folder
我正在通过 Django - Rest - Framework HTTP 将 .zip 文件发布到我的 Django 应用程序。这个 zip 文件是一个包含多个文件的文件夹,其中有一个图像。我想在上传后提取文件夹,select 图像并将其分配给模型。这可能吗?如果没有,也许我可以写一个 属性 来获取缩略图?我希望稍后能够显示图库中的所有缩略图。
类似于:
class FUploadSerializer(serializers.ModelSerializer):
file = serializers.FileField()
class Meta:
model = FUpload
fields = ('created','file')
class FUpload(models.Model):
created = models.DateTimeField(auto_now_add=True)
file = models.FileField(upload_to=get_path)
thumbnail = ImageField() ??? # get from uploaded folder
编辑
我尝试了以下方法,但得到的是:"image":[
"The submitted data was not a file. Check the encoding type on the form."
] 。我是在完全倒退地思考这个问题吗?是否"better" 让客户端处理分别发送图像和.zip 文件夹(数据从脚本发送)? ModelViewSet 是处理这个问题的正确位置吗?
class Thumbnail(models.Model):
image = models.ImageField()
file = models.FileField()
class ThumbnailViewSet(viewsets.ModelViewSet):
queryset = Thumbnail.objects.all()
serializer_class = ThumbnailSerializer
parser_classes = (MultiPartParser, FormParser,)
def perform_create(self, serializer):
file = self.request.FILES['file']
zf = zipfile.ZipFile(file)
content_list = zf.namelist()
imgdata = zf.open(content_list[0])
serializer.save(image=imgdata)
class ThumbnailSerializer(serializers.ModelSerializer):
file = serializers.FileField()
image = serializers.ImageField(allow_empty_file=True, required=False)
class Meta:
model = Thumbnail
fields = ('file', 'image')
为了完成这项工作,您将需要实现自己的自定义解析器,该解析器可以处理传入的 zip 文件、将其解压缩并将某些文件分配给特定字段。
class ZipParser(FileUploadParser):
"""
Parses an incoming ZIP file into separate fields.
The ZIP file is expected to be the only data passed in the request,
use the `MultiPartParser` as a base if it will be passed in using form
data instead.
"""
media_type = 'application/zip' # only needed for `FileUploadParser`
def parse(self, stream, media_type=None, parser_context=None):
import io
import zipfile
parsed = super(ZipParser, self).parse(
self,
media_type=media_type,
parser_context=parser_context
)
data = parsed.files
data['zip_file'] = data['file'] # Keep the original zip file as `zip_file`
parsed_file = data['file'] # Also store a reference to the original file so it can be used
# Try to parse the zip file
# This should also handle proper file handling (such as not passing a zip file)
with zipfile.ZipFile(parsed_file) as zip_file:
# Get the `bytes` object for a file using `read(file_name)`
image_data = zip_file.read('image.png') # Replace `image.png` with the image file
file_data = zip_file.read('info.txt')
# DRF expects that files are using an IO compatible object, so we need `BytesIO` here
image_stream = io.BytesIO(image_data)
file_stream = io.BytesIO(file_data)
# The changed files should go back onto the files dictionary
data['image'] = image_stream
data['file'] = file_stream
return parsed
如果您使用自己的自定义视图,您也可以在将数据传递到序列化程序之前在解析器外部执行此操作。
我正在通过 Django - Rest - Framework HTTP 将 .zip 文件发布到我的 Django 应用程序。这个 zip 文件是一个包含多个文件的文件夹,其中有一个图像。我想在上传后提取文件夹,select 图像并将其分配给模型。这可能吗?如果没有,也许我可以写一个 属性 来获取缩略图?我希望稍后能够显示图库中的所有缩略图。
类似于:
class FUploadSerializer(serializers.ModelSerializer):
file = serializers.FileField()
class Meta:
model = FUpload
fields = ('created','file')
class FUpload(models.Model):
created = models.DateTimeField(auto_now_add=True)
file = models.FileField(upload_to=get_path)
thumbnail = ImageField() ??? # get from uploaded folder
编辑
我尝试了以下方法,但得到的是:"image":[ "The submitted data was not a file. Check the encoding type on the form." ] 。我是在完全倒退地思考这个问题吗?是否"better" 让客户端处理分别发送图像和.zip 文件夹(数据从脚本发送)? ModelViewSet 是处理这个问题的正确位置吗?
class Thumbnail(models.Model):
image = models.ImageField()
file = models.FileField()
class ThumbnailViewSet(viewsets.ModelViewSet):
queryset = Thumbnail.objects.all()
serializer_class = ThumbnailSerializer
parser_classes = (MultiPartParser, FormParser,)
def perform_create(self, serializer):
file = self.request.FILES['file']
zf = zipfile.ZipFile(file)
content_list = zf.namelist()
imgdata = zf.open(content_list[0])
serializer.save(image=imgdata)
class ThumbnailSerializer(serializers.ModelSerializer):
file = serializers.FileField()
image = serializers.ImageField(allow_empty_file=True, required=False)
class Meta:
model = Thumbnail
fields = ('file', 'image')
为了完成这项工作,您将需要实现自己的自定义解析器,该解析器可以处理传入的 zip 文件、将其解压缩并将某些文件分配给特定字段。
class ZipParser(FileUploadParser):
"""
Parses an incoming ZIP file into separate fields.
The ZIP file is expected to be the only data passed in the request,
use the `MultiPartParser` as a base if it will be passed in using form
data instead.
"""
media_type = 'application/zip' # only needed for `FileUploadParser`
def parse(self, stream, media_type=None, parser_context=None):
import io
import zipfile
parsed = super(ZipParser, self).parse(
self,
media_type=media_type,
parser_context=parser_context
)
data = parsed.files
data['zip_file'] = data['file'] # Keep the original zip file as `zip_file`
parsed_file = data['file'] # Also store a reference to the original file so it can be used
# Try to parse the zip file
# This should also handle proper file handling (such as not passing a zip file)
with zipfile.ZipFile(parsed_file) as zip_file:
# Get the `bytes` object for a file using `read(file_name)`
image_data = zip_file.read('image.png') # Replace `image.png` with the image file
file_data = zip_file.read('info.txt')
# DRF expects that files are using an IO compatible object, so we need `BytesIO` here
image_stream = io.BytesIO(image_data)
file_stream = io.BytesIO(file_data)
# The changed files should go back onto the files dictionary
data['image'] = image_stream
data['file'] = file_stream
return parsed
如果您使用自己的自定义视图,您也可以在将数据传递到序列化程序之前在解析器外部执行此操作。