Попробовав несколько возможных решений, я хочу указать на 2 самых простых и наиболее важных из них, которые не требуют переопределения create
метода ни для MyModelSerializer
, ни для внутренних сериализаторов:
- Переопределить метод проверки поля для
config_field
в MyModelSerializer
- Переопределить
validate
метод для всего объекта, сериализуемого с помощью MyModelSerializer
Сериализаторыпредставление внутреннего содержимого config_field
будет одинаковым для обоих решений:
class ConfigVarsSerializer(serializers.Serializer):
id = serializers.IntegerField(required=True)
class ConfigFieldsSerializer(serializers.Serializer):
some_config_int = serializers.IntegerField(required=True)
some_config_vars = serializers.ConfigVarsSerializer(required=True, many=True)
Обратите внимание, что some_config_vars
хранит список объектов, поэтому many=True
.
Решение 1
Переопределить метод проверки поля для config_field
in MyModelSerializer
.В случае данного примера конечный код сериализатора будет:
class MyModelSerializer(serializers.ModelSerializer):
config_field = JSONField(required=False)
class Meta:
model = MyModel
fields = ('config_field', ...)
def validate_config_field(self, value):
serializer = ConfigFieldsSerializer(data=value)
serializer.is_valid(raise_exception=True)
return value
. Этот подход сначала проверяет config_field
, используя значение по умолчанию JSONFieldSerializer
, и вызывает исключение, если содержимое не является действительным JSON
объектом.
Если JSONFieldSerializer
не вызывает исключения, то вызывается validate_custom_fields
, и он передает содержимое поля в ConfigFieldsSerializer
и проверяет весь контент для себя и всех вложенных сериализаторов.
Решение 2
Переопределить метод validate
для всего объекта, сериализуемого с помощью MyModelSerializer
.В случае данного примера конечный код сериализатора будет:
class MyModelSerializer(serializers.ModelSerializer):
config_field = JSONField(required=False)
class Meta:
model = MyModel
fields = ('config_field', ...)
def validate(self, attrs):
config_field = attrs.get('config_field')
if config_field:
serializer = ConfigFieldsSerializer(data=config_field)
serializer.is_valid(raise_exception=True)
return attrs
. Этот подход требует немного больше кода, но позволяет комбинировать проверку config_field
с другими связанными полями.