Sta*_*ute 4 python django django-serializer django-rest-framework
在我的应用程序中,有一个模型将配置存储在其字段之一中。该字段定义为JSONField。我有一个严格的结构来定义该字段的内容应该是什么样子,但我正在努力寻找一种方法来序列化它以验证 API 请求中的数据。
目前有效但不验证内部内容的解决方案config_field是盲目接受任何符合对象要求的内容json:
我的模型的简化版本:
class MyModel(models.Model):
config_field = JSONField(...)
...
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,这是存储在中的数据结构的简化版本config_field:
{"some_config_int": 42, "some_config_vars": [{"id": 1}, {"id": 2}]}
Run Code Online (Sandbox Code Playgroud)
这是我的序列化器的简化版本:
class MyModelSerializer(serializers.ModelSerializer):
config_field = serializers.JSONField(required=False)
class Meta:
model = MyModel
fields = ('config_field', ...)
Run Code Online (Sandbox Code Playgroud)
不过,我想要实现的是为内部内容的嵌套表示(参考 DRF 文档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.ListField(child=ConfigVarsSerializer,required=True)
class MyModelSerializer(serializers.ModelSerializer):
config_field = ConfigFieldsSerializer(required=False)
class Meta:
model = MyModel
fields = ('config_field', ...)
Run Code Online (Sandbox Code Playgroud)
这样,可以选择 POST/PUT 具有配置的对象,但如果config_field位于请求正文中,则应提供整个嵌套对象。
在尝试了几种可能的解决方案之后,我想指出 2 个最简单且最重要的解决方案,这些解决方案既不需要内部序列化器也不需要覆盖create方法:MyModelSerializer
config_field覆盖in的字段验证方法MyModelSerializervalidate正在序列化的整个对象的方法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)
Run Code Online (Sandbox Code Playgroud)
请注意,
some_config_vars存储对象列表,这就是many=True.
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
Run Code Online (Sandbox Code Playgroud)
此方法首先config_field使用默认值进行验证JSONFieldSerializer,如果内容不是有效JSON对象,则引发异常。
如果JSONFieldSerializer没有引发异常,validate_custom_fields则调用它,并将字段的内容传递到ConfigFieldsSerializer并验证其自身和所有嵌套序列化器的所有内容。
重写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
Run Code Online (Sandbox Code Playgroud)
这种方法需要更多的代码,但允许将验证与config_field其他相关字段结合起来。
| 归档时间: |
|
| 查看次数: |
4883 次 |
| 最近记录: |