Django REST framework 嵌套关系的数据保存(Writable nested serializers)

来源:互联网 发布:qq飞车锐速数据官方 编辑:程序博客网 时间:2024/05/21 15:40

利用Django REST framework   能很方便的对Django的model嵌套关系进行展示。嵌套关系的展示通过在序列化类中的depth属性来设置,depth表示嵌套关系展开的层数。比如,Djiango自带的User 模型。User关联了Groups ,同时,Groups又关联了Permission。序列化类定义如下:

class UserSerializer(serializers.ModelSerializer):    class Meta:        model = User        fields = '__all__'        depth = 2

得到的json数据将进行2层的嵌套关系的展开,结果如下:

{    "id": 1,    "username": "admin",     ... ...    "groups": [        {            "id": 1,            "name": "test111",            "permissions": [                {                    "id": 28,                    "name": "Can add 联系人信息",                    "codename": "add_customercontact",                    "content_type": 10                },                {                    "id": 61,                    "name": "Can add market info",                    "codename": "add_marketinfo",                    "content_type": 21                },                {                    "id": 62,                    "name": "Can change market info",                    "codename": "change_marketinfo",                    "content_type": 21                }            ]        }    ],    "user_permissions": [        {            "id": 1,            "name": "Can add log entry",            "codename": "add_logentry",            "content_type": {                "id": 1,                "app_label": "admin",                "model": "logentry"            }        }        ... ...    ]}

虽然这种模式很方便的对数据进行了嵌套展示,但是也带来了一个问题,无法对数据进行保存和更新。

在文档中说明了:

To use writable nested serialization you'll want to declare a nested field on the serializer class, and write the create() and/or update() methods explicitly.

文档中提供的方法,但是感觉不好用。于是,采用了下面这种方式。创建两个序列化类,一个有depth,一个没有depth,如下:

class UserSerializer(serializers.ModelSerializer):    class Meta:        model = User        fields = '__all__'        depth = 2   class UserSerializerNodepth(serializers.ModelSerializer):    class Meta:        model = User        fields = '__all__'
然后在ViewSet中,重载create方法,如下:
  1  def create(self, request):  2         serialized = UserSerializerNoDepth(data=request.data)  3         if serialized.is_valid():  4             serialized.save()  5             return Response(serialized.data)  6         else:  7             return Response(serialized.errors)

关键点在第2行,即利用UserSerializerNoDepth对数据进行序列化,而不是用ViewSet原来指定的UserSerializer进行序列化。这样就能在统一的路由下查看展开的嵌套数据,又能进行数据的保存了。update也是同样的方式:

  1 def update(self, request,pk=None):  2         user=  self.get_object()  3         serialized = UserSerializerNoDepth(user,data=request.data)  4         if serialized.is_valid():  5             serialized.save()  6             return Response(serialized.data)  7         else:  8             return Response(serialized.errors,status=status.HTTP_400_BAD_REQUEST)
0 0