利用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)