django接口开发,使用序列化器的嵌套调用返回Json格式数据
一、背景:
目前正在使用django的restful风格的接口开发,需求是实现数据流加载,后端写好接口,前端调用接口,解析json数据,动态的添加dom元素。我想要将不同的model整合在一起,进行序列化,那么如何整合这些不同的model呢?
方法一:
根据官方文档找到的答案:
采用多个序列化进行嵌套:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class ProfileSerializer(serializer,ModelSerializer): class Meta: model = profle fields = '__all__'
class UserSerializer(serializers.ModelSerializer): profile = ProfileSerializer()
class Meta: model = User fields = ['username', 'email', 'profile']
def create(self, validated_data): profile_data = validated_data.pop('profile') user = User.objects.create(**validated_data) Profile.objects.create(user=user, **profile_data) return user
|
法二:
常用的是以下这种嵌套,因为这种方法不仅可以嵌套,还可以递归调用序列化器,只需要在get_commodity
中返回的是当前这个序列化器,就可以了,可以用于评论的多级递归序列化调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Order_detailsSerializer(serializers.ModelSerializer): """ 订单商品详情序列化容器 The serializer of Order_details which used to combine with Order_basic """
commodity = serializers.SerializerMethodField()
def get_commodity(self, obj): commodity = Commodity.commodity_.filter(order_details=obj.pk) if len(commodity) > 0: return CommoditySerializer(commodity, many=True).data return ''
class Meta: model = Order_details fields = ('price', 'commodity', 'commodity_counts')
|
使用serializers.SerializerMethodField()
指明所要嵌套的字段。然后重写get_commodity
的方法,获取另一个序列化器的数据,作为该字段的值。
这样一来,我就可以序列化多个model,组成json格式的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| [ { "order_id": 1, "trade_number": "102301230213021", "total_price": "9999.0", "commodity_total_counts": 100, "generate_time": "2020-05-26T15:07:08", "status": "1", "order_details": [ { "price": "50.00", "commodity": [ { "store_name": "店铺1", "commodity_name": "貂皮大衣", "intro": "舒适的不要不要的", "category": "衣服", "discounts": false, "freight": 0, "image": null } ], "commodity_counts": 25 }, { "price": "100.00", "commodity": [ { "store_name": "店铺1", "commodity_name": "貂皮大衣", "intro": "舒适的不要不要的", "category": "衣服", "discounts": false, "freight": 0, "image": null } ], "commodity_counts": 25 } ] },
|
二、自定义序列化格式
但问题又来了,我之前设计数据表的时候,针对choices字段的二元祖,我为了减少数据库的字段所使用的数据类型大小,采用1个字节的字符串来代替具体的汉子,比如
1 2 3 4 5 6 7 8 9 10
| status_choice = ( ("1", '代付款'), ("2", '代发货'), ("3", '交易成功'), ("4", '已取消'), ("5", '售后中'), ("6", '交易关闭'), )
|
但是status
在已经序列化JSON格式中为”1”,而不是可读的汉子,因此我还需要针对该字段进行自定义序列化。
具体的方法有两种:
法一:
1 2 3 4 5 6 7 8 9 10 11
| class Order_basicSerializer(serializers.ModelSerializer): """订单序列化容器"""
order_details = serializers.SerializerMethodField()
status = serializers.SerializerMethodField()
def get_status(self, obj): return obj.get_status_display()
|
说明:同样采用serializers.SerializerMethodField()
方法指定字段,然后通过get_status
方法获取可读字段。这种方法适用于不同的序列化器中,比较灵活,但如果多个序列化器都要获取某一个字段的可读形式,代码量就比较多了。因此还有第二种方法。
法二:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class ChoiceDisplayField(serializers.ChoiceField):
def to_representation(self, value): """针对value(choice)转成我们需要的格式""" return self.choices[value] class Order_basicSerializer(serializers.ModelSerializer): """订单序列化容器""" status_choice = ( ("1", '代付款'), ("2", '代发货'), ("3", '交易成功'), ("4", '已取消'), ("5", '售后中'), ("6", '交易关闭'), ) status = ChoiceDisplayField(choices=status_choice)
|
说明:这种方法通过自定义序列化,获取choice中的可读字段值。这种方法好处在于自定义的序列化类可以重用,但是需要冗余选择项,类似status_choice,特别是在继承了serializers.ModelSerializer
后。
这样:经过序列化后,就可以返回可读的status。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| [ { "order_id": 1, "trade_number": "102301230213021", "total_price": "9999.0", "commodity_total_counts": 100, "generate_time": "2020-05-26T15:07:08", "status": "代付款", "order_details": [ { "price": "50.00", "commodity": [ { "store_name": "店铺1", "commodity_name": "貂皮大衣", "intro": "舒适的不要不要的", "category": "衣服", "discounts": false, "freight": 0, "image": null } ], "commodity_counts": 25 }, { "price": "100.00", "commodity": [ { "store_name": "店铺1", "commodity_name": "貂皮大衣", "intro": "舒适的不要不要的", "category": "衣服", "discounts": false, "freight": 0, "image": null } ], "commodity_counts": 25 } ] }
|