Как обновить вложенные сериализаторы с файловым полем - PullRequest
0 голосов
/ 21 января 2019

У меня есть 2 модели: Профиль и Изображение .Поле профиля "логотип" связано с изображением с моделированием. Конструкция ForeignKey ().Я хочу обновить запись моего профиля с помощью запроса на обновление (исправление с полезной нагрузкой JSON).

Как я могу это сделать?

Я пытался отправить этот JSON

{
    "name": "TestName",
    "company": "myCompany",
    "phone": "33222111",
    "website": "site.com"
}

И все в порядке, запись обновлена.Но!В модели изображений у меня есть модели. ImageField ().Как мне разобраться с этим полем через другой сериализатор?

Затем я попытался отправить этот JSON (122 идентификатора существующей записи изображения в БД)

REQUEST:
{
   "logo": 122
}

ANSWER:
{
    "logo": {
        "non_field_errors": [
            "Invalid data. Expected a dictionary, but got int."
        ]
    }
}

ОК, так что подумайтеМне надо отправить объект существующей записи

REQUEST:
{
   "logo": {
        "id": 122,
        "uuid": "bf9ba033-208f-47e0-86e5-93c44e05a616",
        "created": "2018-12-20T12:54:57.178910Z",
        "original_name": "hello.png",
        "filetype": "png",
        "file": "http://localhost/upload/img/0a9lg1apnebb.png",
        "owner": 1
   }
}

ANSWER:
{
    "logo": {
        "file": [
            "The submitted data was not a file. Check the encoding type on the form."
        ]
    }
}

Вот мои две модели и сериализаторы

class Image(models.Model):
    id = models.AutoField(primary_key=True)
    uuid = models.UUIDField(primary_key=False, default=uuid.uuid4, editable=False)
    created = models.DateTimeField(auto_now_add = True)
    original_name = models.CharField(max_length = 256, default=None)
    filetype = models.CharField(max_length = 10, default=None)
    file = models.ImageField(upload_to=update_img_filename,
                         default="static/noimg.jpg")
    owner = models.ForeignKey(User, related_name="images",
                          on_delete=models.CASCADE, null=True)


class Profile(models.Model):
    user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE)
    name = models.CharField(max_length=256, blank=True, null=True)
    company = models.CharField(max_length=256, blank=True, null=True)
    phone = models.CharField(max_length=256, blank=True, null=True)
    website = models.CharField(max_length=256, blank=True, null=True)
    logo = models.ForeignKey(Image, related_name="profile_logo",
                                on_delete=models.SET_NULL, null=True,
                                blank=True, default=None)
    is_admin = models.BooleanField(default=False)
    owner = models.ForeignKey(User, related_name="profiles",
                          on_delete=models.CASCADE, null=True)

class ProfileSerializer(serializers.ModelSerializer):
    logo = ImageSerializer()

    class Meta:
        model = Profile
        fields = '__all__'
        extra_kwargs = {
            'owner': {'read_only': True},
            'user': {'read_only': True},
            'is_admin': {'read_only': True},
        }

    def create(self, validated_data):
        return Profile.objects.create(**validated_data)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

class ImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = Image
        fields = '__all__'
        extra_kwargs = {
            'owner': {'read_only': True}
        }

    def validate(self, data):
        extension = str(data['file']).split(".")[-1].lower()
        original_name = str(data['file'])

        if 'original_name' not in data:
            data['original_name'] = original_name
        if 'filetype' not in data:
            data['filetype'] = extension

        return data

    def create(self, validated_data):
        return Image.objects.create(**validated_data)

Ответы [ 2 ]

0 голосов
/ 18 апреля 2019

если вам нужно установить изображение только из существующих изображений, вы можете сделать это:

class ProfileSerializer(serializers.ModelSerializer):
    logo = ImageSerializer()

    class Meta:
        model = Profile
        fields = '__all__'
        extra_kwargs = {
            'owner': {'read_only': True},
            'user': {'read_only': True},
            'is_admin': {'read_only': True},
        }

class ImageSerializer(serializers.ModelSerializer):

    def to_internal_value(self, data):
        return Image.objects.get(pk=data)

    class Meta:
        model = Image
        fields = '__all__'
        extra_kwargs = {
            'owner': {'read_only': True}
        }
...

Тогда вы можете отправить json:

{
    "name": "TestName",
    "company": "myCompany",
    "phone": "33222111",
    "website": "site.com"
    "logo": 122
}

И изображение будет установлено.

0 голосов
/ 21 января 2019

в базе данных, модель Profile будет иметь logo_id отображение с моделью Image.Попробуйте json вот так, если вы хотите иметь отношения с существующим логотипом:

{
    "name": "TestName",
    "company": "myCompany",
    "phone": "33222111",
    "website": "site.com",
    "logo: 122
}




class ProfileSerializer(serializers.ModelSerializer):
    logo = ImageSerializer()

    class Meta:
        model = Profile
        fields = '__all__'
        extra_kwargs = {
            'owner': {'read_only': True},
            'user': {'read_only': True},
            'is_admin': {'read_only': True},
        }
    def create(self, validated_data):
        logo_id = validated_data.pop('logo')
        profile = Profile.objects.create(**validated_data)
        logo_instance = Image.objects.get(pk=logo_id)
        profile.logo = logo_instance
        profile.save()

    def update(self, instance, validated_data):
        nested_serializer = self.fields['logo']
        nested_instance = instance.profile
        nested_data = validated_data.pop('logo')
        nested_serializer.update(nested_instance, nested_data)
        return super(ProfileSerializer, self).update(instance, validated_data)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...