在DRF中进行POST时,在何处创建对象以及如何有效地验证复杂的JSON字段?

时间:2015-08-04 00:34:48

标签: django django-rest-framework

在这里完成DRF初学者......我对以下概念感到困惑:

  1. 让我们说一些数据,包括其中一个字段的复杂JSON blob,以便创建一个对象。我应该在哪里创建这个对象?看看3.1文档,看起来两个地方对此同样有效:Serializer.create()和ViewSet.create()。我如何决定在哪里创建我的对象以及考虑哪种方式"规范"?

  2. 我知道我需要运行Serializer.is_valid()才能验证POSTed数据。但是,.data和.validated_data之间有什么区别?它们看起来是一样的。

  3. 最后,什么是"规范"使用JSONField的方法(例如django-jsonfield,但我没有与这个包/实现结合)?我有一个带有几个JSONFields的模型,并希望正确使用它#34;正确"在DRF。我知道https://stackoverflow.com/a/28200902/585783,但它似乎不够。

  4. 编辑:我的用例是一个API POST,其中包含一个字段中的复杂JSON blob。我需要解析JSON字段,验证它,基于它获取/创建多个对象,链接新对象和现有对象,最后将JSON字段存储在其中一个新对象中。因此,我需要通过将其解析为python来对此JSON字段进行自定义验证:

    from django.utils.six import BytesIO
    from rest_framework.parsers import JSONParser
    
    class MySerializer(serializers.ModelSerializer):
        my_json_field = JSONSerializerField()
    
        def validate_my_json_field(self, value):
            stream = BytesIO(value)
            list_of_dicts = JSONParser().parse(stream)
            # do lots of validation to list_of_dicts
            # render list_of_dicts back to a JSON string
            return validated_list_of_dicts_as_json
    

    现在,根据我在概念1中选择的方式,我必须再次解析经过验证的JSON以在create()中创建我的对象,这感觉不对。

    提前致谢!

1 个答案:

答案 0 :(得分:3)

HTTP请求(POST,GET,PUT,DELETE)的内容将始终由视图(View,APIView,通用视图,视图集)处理。序列化程序只是这些视图处理请求的一部分。序列化程序是将View层与Model层连接的“手段”。有关序列化程序的具体内容,请阅读此page官方文档的第一段。

回答#1:除非你有一个非常具体的用例,否则你几乎总是不需要触摸它们。在那些特殊情况下:

  • 如果必须自定义模型的方式,则覆盖Serializer.create() 实例转换为本机Python对象,反之亦然。 (例如创建多个对象)
  • 如果您需要自定义实际请求本身的处理方式,则覆盖ViewSet.create()。 (例如,如果请求中有其他查询参数,请添加一些响应标头)

要回答#2,在使用通用视图或ViewSet时几乎不需要使用is_valid()。他们已经为你做了它。序列化程序的.data.validated_data有点难以解释。前者包含要序列化的查询集/模型实例的Python数据类型表示,而后者是验证过程涉及检查Python对象是否符合前面提到的特定Python数据类型表示的结果,而后者又可以是转换为模型实例。如果这没有意义,请参阅Serializing objectsDeserializing objects

至于#3,JSON字段是什么意思?据我所知,Django没有名为JSONField的模型字段。这是来自第三方软件包还是您自己的自定义书面模型字段?如果是这样,那么您可能必须找到或编写一个包,让您可以顺利地“正确”地将它与DRF集成。

修改
你的用例太复杂了。我只能给你这个粗略的代码。

class MyModelSerializer(serializers.ModelSerializer):
    my_json_field = JSONSerializerField()

    class Meta:
        model = MyModel

    def validate(self, data):
        # Get JSON blob
        json_blob = data['my_json_field']
        # Implement your own JSON blob cleanup method
        # Return None if invalid
        json_blob = clean_json_blob(json_blob)
        # Raise HTTP 400 with your custom error message if not valid
        if not json_blob:
            raise serializers.ValidationError({'error': 'Your error message'})
        # Reassign if you made changes and return
        data['my_json_field'] = json_blob
        return data

    def create(self, validated_data):
        json_blob = validated_data['my_json_field']
        # Implement your object creation here
        create_all_other_objects_from_json(json_blob)
        # ...
        # Then return a MyModel instance
        return my_model