我正在尝试在Django Web应用程序中启用部分更新(使用Django Rest Framework)。
我要更新的模型包括ImageField。
当我更新ImageField时,PATCH方法有效,但是当我不更新ImageField时,PATCH方法不起作用。
错误消息说
AttributeError:'NoneType' object has no attribute 'items'
我该如何解决?
型号:
class Work(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True, blank=True)
title = models.CharField(max_length=120)
made_date = models.DateField(default=datetime.date.today, null=True, blank=True)
note = models.TextField(max_length=2000, null=True, blank=True)
image = models.ImageField(upload_to='work_pic', default='default_image.png')
def __str__(self):
return self.title
def save(self, *args, **kwargs):
if self.image and self.image.name.lower().endswith(('.jpg', '.jpeg')):
pilImage = Img.open(BytesIO(self.image.read()))
for orientation in ExifTags.TAGS.keys():
if ExifTags.TAGS[orientation] == 'Orientation':
break
exif = dict(pilImage._getexif().items())
if exif[orientation] == 3:
pilImage = pilImage.rotate(180, expand=True)
elif exif[orientation] == 6:
pilImage = pilImage.rotate(270, expand=True)
elif exif[orientation] == 8:
pilImage = pilImage.rotate(90, expand=True)
output = BytesIO()
pilImage.save(output, format='JPEG', quality=75)
output.seek(0)
self.image = File(output, self.image.name)
return super(Work, self).save(*args, **kwargs)
序列化器:
class WorkSerializer(serializers.ModelSerializer):
owner = serializers.HiddenField(default=serializers.CurrentUserDefault())
class Meta:
model = Work
fields = '__all__'
def create(self, validated_data):
return Work.objects.create(**validated_data)
ViewSet:
class WorkViewSet(viewsets.ModelViewSet):
queryset = Work.objects.all()
serializer_class = WorkSerializer
def partial_update(self, request, *args, **kwargs):
kwargs['partial'] = True
return self.update(request, *args, **kwargs)
发送请求的方法(Vue.js):
updateWork: function() {
let formData = new FormData();
//Initial value of currentWork.image is text (path to the original image in the media folder).
//When user upload new image, the file is set to currentWork.image. So condition is match to the if statement bellow.
if (this.currentWork.image instanceof File) {
formData.append("image", this.currentWork.image);
}
formData.append("title", this.currentWork.title);
formData.append("made_date", this.currentWork.made_date);
formData.append("note", this.currentWork.note);
this.loading = true;
axios.patch(`/api/work/${this.currentWork.id}/`, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then((response) => {
this.loading = false;
})
.catch((err) => {
this.loading = false;
console.log(err);
})
错误消息:
Internal Server Error: /api/work/61/
Traceback (most recent call last):
File "/Users/rami/Dev/MySweetsBase/myvenv/lib/python3.6/site-packages/django/core/handlers/exception.py", line 35, in inner
response = get_response(request)
File "/Users/rami/Dev/MySweetsBase/myvenv/lib/python3.6/site-packages/django/core/handlers/base.py", line 128, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/Users/rami/Dev/MySweetsBase/myvenv/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/rami/Dev/MySweetsBase/myvenv/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/rami/Dev/MySweetsBase/myvenv/lib/python3.6/site-packages/rest_framework/viewsets.py", line 103, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/rami/Dev/MySweetsBase/myvenv/lib/python3.6/site-packages/rest_framework/views.py", line 483, in dispatch
response = self.handle_exception(exc)
File "/Users/rami/Dev/MySweetsBase/myvenv/lib/python3.6/site-packages/rest_framework/views.py", line 443, in handle_exception
self.raise_uncaught_exception(exc)
File "/Users/rami/Dev/MySweetsBase/myvenv/lib/python3.6/site-packages/rest_framework/views.py", line 480, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/rami/Dev/MySweetsBase/works/viewsets.py", line 13, in partial_update
return self.update(request, *args, **kwargs)
File "/Users/rami/Dev/MySweetsBase/myvenv/lib/python3.6/site-packages/rest_framework/mixins.py", line 70, in update
self.perform_update(serializer)
File "/Users/rami/Dev/MySweetsBase/myvenv/lib/python3.6/site-packages/rest_framework/mixins.py", line 80, in perform_update
serializer.save()
File "/Users/rami/Dev/MySweetsBase/myvenv/lib/python3.6/site-packages/rest_framework/serializers.py", line 209, in save
self.instance = self.update(self.instance, validated_data)
File "/Users/rami/Dev/MySweetsBase/myvenv/lib/python3.6/site-packages/rest_framework/serializers.py", line 981, in update
instance.save()
File "/Users/rami/Dev/MySweetsBase/works/models.py", line 26, in save
exif = dict(pilImage._getexif().items())
AttributeError: 'NoneType' object has no attribute 'items'
答案 0 :(得分:0)
class Work(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True, blank=True)
title = models.CharField(max_length=120)
made_date = models.DateField(default=datetime.date.today, null=True, blank=True)
note = models.TextField(max_length=2000, null=True, blank=True)
image = models.ImageField(upload_to='work_pic', default='default_image.png')
def __str__(self):
return self.title
def save(self, *args, **kwargs):
if not self.id:
# add
self.set_image()
else:
# change
this = Work.objects.get(id=self.id)
if this.image != self.image:
self.set_image()
return super(Work, self).save(*args, **kwargs)
def set_image(self):
if self.image and self.image.name.lower().endswith(('.jpg', '.jpeg')):
pilImage = Img.open(BytesIO(self.image.read()))
for orientation in ExifTags.TAGS.keys():
if ExifTags.TAGS[orientation] == 'Orientation':
break
exif = dict(pilImage._getexif().items())
if exif[orientation] == 3:
pilImage = pilImage.rotate(180, expand=True)
elif exif[orientation] == 6:
pilImage = pilImage.rotate(270, expand=True)
elif exif[orientation] == 8:
pilImage = pilImage.rotate(90, expand=True)
output = BytesIO()
pilImage.save(output, format='JPEG', quality=75)
output.seek(0)
self.image = File(output, self.image.name)
尝试一下