В моей модели JSONField
, в котором хранятся некоторые данные конфигурации.Я хочу получить доступ к этому полю (как чтение, так и запись) с возможностью частичного обновления внутренних полей и их значений.
В целях примера пусть модель будет называться MyModel
, а JSONField
называется config
:
class MyModel(models.Model):
config = JSONField(default=dict())
...
Я создал отдельный ViewSet
для доступа к информации, хранящейся в config
поле.Предположим, что модель user
имеет отношение ForeignKey
к MyModel
.Упрощенная версия этого ViewSet
:
class ConfigurationFieldViewSet(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, viewsets.GenericViewSet):
serializer_class = MyModelConfigurationSerializer
def get_object(self):
return self.request.user.my_model
Данные, хранящиеся в config
, имеют определенную структуру с несколькими возможными внутренними объектами:
{
"C1": {"counter": 42, "active": false},
"C2": {"counter": 13, "active": true}
}
Для доступа и правильной сериализации MyModel
Экземпляр на всех уровнях вложенности. Я создал сериализаторы для каждого уровня поля.Для доступа к полю config
в самом MyModel
я использую этот сериализатор:
class MyModelConfigurationSerializer(serializers.ModelSerializer):
configuration = ConfigurationFieldSerializer(required=True)
class Meta:
model = MyModel
fields = ('configuration',)
Для доступа и сериализации первого слоя поля configuration
есть второй сериализатор:
class ConfigurationFieldSerializer(serializers.Serializer):
C1 = BaseConfigurationSerializer(required=True)
C2 = BaseConfigurationSerializer(required=True)
Наконец, для доступа к внутренней структуре каждого поля C1
и C2
существует третий сериализатор:
class BaseConfigurationSerializer(serializers.Serializer):
counter = serializers.IntegerField(
required=False,
help_text=_('Some integer field help text')
)
active = serializers.BooleanField(
required=False,
help_text=_('Some boolean field description')
)
Приведенный выше код отлично работает для чтения данных, хранящихся в поле config
, и корректной сериализации его внутренних объектов.,Проблема возникает, когда я пытаюсь выполнить PUT
в этом поле.
Если я переопределяю update
метод на уровне MyModelConfigurationSerializer
, то сериализаторы проверяют данные, которые я отправляю, но в виде чанка иЯ могу сохранить все сразу.Если я пытаюсь передать какое-то внутреннее поле, я все еще правильно получаю ошибки проверки внутренними сериализаторами.
def update(self, instance, validated_data):
instance.configuration = validated_data.get(
'configuration', instance.configuration
)
instance.save()
return instance
Что я не могу сделать, так это вызвать update
методы внутренних сериализаторов (ConfigurationFieldSerializer
и BaseConfigurationSerializer
в этом случае): если я реализую их update
методы, они просто не будут вызваны.
Согласно Документация DRF возможны записываемые вложенные представления и соответствуют update
или create
методы должны вызываться всякий раз, когда update
вызывается на сериализаторе верхнего уровня.