Python 如何使用Django Rest框架清除图像?
我原以为我的问题应该由解决,但似乎,无论我发送的是无字符串还是空字符串,DRF都不高兴 我使用的是Django1.11.6和DRF3.7.7Python 如何使用Django Rest框架清除图像?,python,django,image,rest,django-rest-framework,Python,Django,Image,Rest,Django Rest Framework,我原以为我的问题应该由解决,但似乎,无论我发送的是无字符串还是空字符串,DRF都不高兴 我使用的是Django1.11.6和DRF3.7.7 class Part(models.Model): image = models.ImageField(null=True, blank=True) class PartSerializer(serializers.ModelSerializer): class Meta: model = Part fie
class Part(models.Model):
image = models.ImageField(null=True, blank=True)
class PartSerializer(serializers.ModelSerializer):
class Meta:
model = Part
fields = ('id', 'image')
class PartDetail(generics.RetrieveUpdateAPIView):
queryset = Part.objects.all()
serializer_class = PartSerializer
parser_classes = (MultiPartParser, FormParser)
# put image, works fine
with tempfile.NamedTemporaryFile(suffix='.jpg') as fp:
image = Image.new('RGB', (100, 200))
image.save(fp)
fp.seek(0)
data = {'image': fp}
self.client.put('/path/to/endpoint', data, format='multipart')
# clear image, attempt #1
data = {'image': None}
self.client.put('/path/to/endpoint', data, format='multipart')
AssertionError: {'image': ['The submitted data was not a file. Check the encoding type on the form.']}
# clear image, attempt #2
data = {'image': ''}
self.client.put('/path/to/endpoint', data, format='multipart')
AssertionError: <ImageFieldFile: None> is not None
类零件(models.Model):
image=models.ImageField(null=True,blank=True)
类PartSerializer(serializers.ModelSerializer):
类元:
型号=零件
字段=('id','image')
类PartDetail(generics.RetrieveUpdateAppiview):
queryset=Part.objects.all()
serializer\u class=PartSerializer
parser_classes=(MultiPartParser,FormParser)
#把图像放进去,效果很好
使用tempfile.NamedTemporaryFile(后缀='.jpg')作为fp:
image=image.new('RGB',(100200))
图像保存(fp)
fp.seek(0)
数据={'image':fp}
self.client.put('/path/to/endpoint',data,format='multipart')
#清除图像,尝试#1
数据={'image':无}
self.client.put('/path/to/endpoint',data,format='multipart')
AssertionError:{'image':['提交的数据不是文件。请检查表单上的编码类型。']}
#清除图像,尝试#2
数据={'image':'''}
self.client.put('/path/to/endpoint',data,format='multipart')
AssertionError:不是无
必须明确指定图像字段以允许其为空
使用以下命令:
class PartSerializer(serializers.ModelSerializer):
image = serializers.ImageField(max_length=None, allow_empty_file=True, allow_null=True, required=False)
class Meta:
model = Part
fields = ('id', 'image')
查看更多详细信息。请确保我重新实现了您的代码
Django version:2.0
DRF version:3.7.7 as you say in the question.
首先,结论是您尝试的方法#2在我的测试中是正确的。但是,尝试1无效,我的错误与你的相同。但是,以前保存的映像不会在文件系统中删除。以下是我的测试用例。确保您使用的是DRF提供的客户端,而不是django本身
from PIL import Image
from django.test import Client
import io
import os
import unittest
from rest_framework.test import APIClient
class PutTests(unittest.TestCase):
def generate_photo_file(self):
file = io.BytesIO()
image = Image.new('RGBA', size=(100, 100), color=(155, 0, 0))
image.save(file, 'png')
file.name = 'test222.png'
file.seek(0)
return file
def test_imagetest(self):
"""
test put Image object
:return:
"""
self.client = Client()
print(os.path.join(os.path.dirname( os.path.dirname(__file__) ), '2018s.jpg'))
f = self.generate_photo_file()
data={
'image': f,
}
# if you want to insert image in the testCase please let class PartDetail inherits from ListCreateAPIView.
self.client.post('/puttestimage/', data=data, format='multipart')
def test_image2test(self):
# this won't work in my test.
self.client = APIClient()
data = {'image': None}
self.client.put('/puttestimage/1/', data=data, format='multipart')
#
def test_image3test(self):
# this will work in my test.
self.client = APIClient()
data = {'image': ''}
self.client.put('/puttestimage/2/', data=data, format='multipart')
基本的想法是,我首先在数据库中插入一个图像,然后我通过您的尝试#1和#2清除这个图像
class PartSerializer(serializers.ModelSerializer):
#image=serializers.ImageField(max_length=None,allow_empty_file=True,allow_null=True,required=False)
类元:
型号=零件
字段=('id','image')
类PartDetail(generics.RetrieveUpdateAppiview):
queryset=Part.objects.all()
serializer\u class=PartSerializer
parser_classes=(MultiPartParser,FormParser)
URL模式=[
url(r'puttestimage/(?P[0-9]+)/”,PartDetail.as_view(),name='imageput'),
url(r'puttestimage/',PartDetail.as_view(),name='imageput'),
]
这在文件的文档字段中有介绍。删除
我将在序列化程序上创建一个update
方法,该方法将使用ORM调用清除图像
def update(self, instance, validated_data):
instance.part.delete(save = True)
或者类似的东西。我在尝试编写一个Angular应用程序时遇到了类似的情况,该应用程序通过Django REST框架与Django系统联系。DRF自动生成用于更新对象的表单。如果对象上有一个
文件字段
,并且您在提交文件时没有将文件上载到更新表单中,框架可以自动删除以前上载的文件,使对象完全没有文件。然后,对象的字段为空。我希望我的应用程序具有此功能,也就是说,对象可以有一个附加文件,但这不是必需的,并且文件可以附加并在以后删除。我试图通过构造一个FormData
对象并将其作为PUT请求发送来完成删除,但我无法准确地确定要为文件字段指定什么值以使DRF删除以前上载的文件,就像DRF自动生成的表单中发生的情况一样
这些都不起作用:
让fd=newformdata();
fd.set('my_file',null);//TypeScript不允许我这么做
fd.set('my_file','');//与您的尝试相同的错误#2
fd.set('my_file',new Blob([]);//关于空文件的错误
最终奏效的是
fd.set('my_file',新文件([],'');
这显然意味着一个没有名字的空文件。这样,我可以发送一个PUT请求,删除附加到对象的文件,并将结果文件字段保留为空:
this.http.put(url,fd);
其中this.http
是一个角度HttpClient
。我不知道如何在Python中构造这样一个PUT请求
要保留文件,请不要在FormData
上为'my\u file'
设置任何内容
在Django方面,我使用了ModelSerializer
的子类作为序列化程序,模型中的底层文件字段有blank=True,null=True的选项。对不起,我忘了提到我使用的是Django 1.11.6(和DRF 3.7.7)。我尝试了这个,并发送了None
(尝试1)和'
(尝试2)产生同样的结果。最短和有效的最佳答案。你是如何解决这个问题的?
def update(self, instance, validated_data):
instance.part.delete(save = True)