图片不存在validated_data中

时间:2018-06-25 00:50:08

标签: django django-rest-framework

问题:

我正在尝试实现对Profile模型进行序列化的Serializer。不幸的是,image键及其值在传递给串行器的validated_data方法的update()中不存在。


设置:

这是我正在测试的环境:
Django 1.11.4djangorestframework 3.6.3Python 3.6.5

这是我用于将其放置到相应端点的请求:

curl -vvv \
     -XPUT \
     -H "Authorization:Bearer ${accessToken}" \
     -H "Content-Type:multipart/form-data" \
     -F "user=http://${baseURL}/users/2;type=application/json" \
     -F "image=@${image1};type=image/png" \
     ${url}

序列化程序代码:

from rest_framework import serializers

class ImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = Image
        fields = ('image',)

    image = serializers.ImageField(required=True)


class ProfileSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Profile
        fields = (
            'url',
            'user',
            'image',
            )

    image = ImageSerializer(required=False, allow_null=True)

    def update(self, instance, validated_data):
        # The documentation tells me it should now work like this:
        uploaded_image = validated_data.pop('image')
        instance.image = ProfileImage.objects.create(image=uploaded_image)
        return super().update(instance, validated_data)
        # but validated_data.pop('image') raises a KeyError which is logical, 
        # since validated_data does not contain an 'image' key.

型号代码:

from django.db import models
from django.contrib.auth import get_user_model

class Image(models.Model):
    image = models.ImageField(null=True, default=None)

    class Meta:
        abstract = True


class ProfileImage(Image):
    pass


class Profile(models.Model):
    user = models.OneToOneField(get_user_model(), related_name='profile')
    image = models.OneToOneField(ProfileImage, related_name='profile', null=True, default=None)

当我在序列化器的update()方法内设置断点并检查validated_data时,不存在图像键值对,这就是validated_data.pop('image')(建议{{3 }})引发KeyError。


可能的解决方法?

但是我可以像这样从请求数据中检索图像并手动更新模型:

def update(self, instance, validated_data):
    uploaded_image = self.context.get('request').data.get('image')
    instance.image = ProfileImage.objects.create(image=uploaded_image)
    return super().update(instance, validated_data)

但是,这对我来说似乎很棘手,因为我认为也必须有某种方法也可以使图像出现在validated_data中。


问题:

  • 建议的手动方法是可以接受的还是不好的技巧?
  • 为什么图像键值对在validated_data中不存在?
  • 应该存在吗?

到目前为止,我已经尝试过:

我已经在ProfileSerializer中实现了validate()覆盖,检查了传递给它的attrs,图像不在其中。

我已经在ProfileSerializer和ImageSerializer上实现了validate_image(),但均未调用。

我已经在ImageSerializer中实现了validate()update()覆盖,但没有一个被调用。

2 个答案:

答案 0 :(得分:0)

问题是请求中的名称INSERT INTO Student_Interest (Id_Student, Id_Interest, Score) SELECT Id_Student, Id_Interest, i.Score FROM Student s CROSS JOIN (SELECT TOP (5) Score FROM Interest ORDER BY NEWID()) i; 与嵌套字段名称image不匹配。

field name didn't match, Serializer.get_value() returns 'empty'起,
这导致image.image跳过the field entirely

基本上,只是默默地忽略了身体部位。

要使其正常运行,我必须将请求更改为此:

Serializer.to_internal_value()

答案 1 :(得分:-1)

来自Django Rest Framework's documentation

  

默认情况下,嵌套的序列化器是只读的。如果你想支持   您需要创建对嵌套序列化器字段的写操作   create()和/或update()方法以明确指定如何   子关系应该保存。

在您的示例中,您应该使用update方法手动更新相关对象:

def update(self, instance, validated_data):
    if 'image' in validated_data:
        instance.image.image = validated_data.pop('image')
    ...

    instance.save()
    return instance