django-parler-rest icon indicating copy to clipboard operation
django-parler-rest copied to clipboard

Partial Update Doesn't Work

Open ishakoktn opened this issue 2 years ago • 1 comments

When I try to update with PATCH it doesn't work. Asks me to fill all fields.

Do you have any special reason to do not to support this?

My usage is like this:

  class MySerializer(TranslatableModelSerializer):
      translations = TranslatedFieldsField(shared_model=MyModel)
      
      class Meta:
          model = MyModel
          fields = '__all__'

For solving this problem I need to override the to_internal_value method:

class ParialUpdatableTranslatedFieldsField(TranslatedFieldsField):
        
         def to_internal_value(self, data):
             ...
             
             # replace this line with below
             # serializer = self.serializer_class(
             #    data=model_fields
             # ) 
          
             serializer = self.serializer_class(
                data=model_fields,
                context=self.context,
                partial=self.parent.partial,
            )
            ...

ishakoktn avatar May 23 '22 13:05 ishakoktn

Maybe it's related but I couldn't get any kind of update working. I always got an error like this:

TypeError: 'MyModelTranslation' instance expected, got 'en'

However I could get this "fixed" by creating my own TranslatableModelSerializer class like this:

from parler_rest.fields import TranslatedField, TranslatedFieldsField
from parler_rest.serializers import TranslatableModelSerializer

class UpdateableTranslatableModelSerializer(TranslatableModelSerializer):
    def update(self, instance, validated_data):
        translated_data = self._pop_translated_data_for_update(validated_data)
        instance = super().update(instance, validated_data)
        self.save_translations(instance, translated_data)
        return instance

    def _pop_translated_data_for_update(self, validated_data):
        translated_data = {}
        for field_name, field in self.get_fields().items():
            if isinstance(field, (TranslatedField, TranslatedFieldsField)):
                key = field.source or field_name
                translations = validated_data.pop(key, None)
                if translations:
                    translated_data[key] = translations
        return translated_data

And when I changed my serializers to inherit from that class I got both partial and full updates working.

RauliL avatar Feb 09 '23 10:02 RauliL