drf——嵌套序列化器(多表联合查询)

models

class TbGroupBookingInfo(models.Model):
    product_group_booking_id = models.PositiveIntegerField()
    pid = models.PositiveIntegerField()
    status = models.PositiveIntegerField()
    end_date = models.DateTimeField()
    price_deposit = models.IntegerField()
    price_online = models.IntegerField()
    create_date = models.DateTimeField()
    uid = models.PositiveBigIntegerField()
    max_member_cnt = models.PositiveIntegerField()
    real_member_cnt = models.PositiveIntegerField()
    is_supplement_master = models.PositiveIntegerField()

    class Meta:
        managed = False
        db_table = 'tb_group_booking_info'
        verbose_name = '拼团团属性详情表'
        app_label = 'order'


class TbGroupBookingUser(models.Model):
    group_booking_info = models.ForeignKey(to=TbGroupBookingInfo, on_delete=models.DO_NOTHING,
                                           db_constraint=False,
                                           db_column='group_booking_info_id', related_name='booking_info')
    uid = models.PositiveBigIntegerField()
    pid = models.PositiveIntegerField()
    status = models.PositiveIntegerField()
    create_date = models.DateTimeField()

    class Meta:
        managed = False
        db_table = 'tb_group_booking_user'
        unique_together = (('group_booking_info_id', 'uid'),)
        verbose_name = '拼团团成员表'
        app_label = 'order'

需要注意的如下几个参数:

  • ForeignKey外键关联,一般有关联关系的,都是主动更改为外键关联
  • to关联的model类名,可以使用字符串,也可以使用类名,个人偏向于类名
  • on_delete级联删除,一般作为测试人员,我们设置为models.DO_NOTHING,但需要知道,正确的设置应该是级联删除,但测试本来就会构造出很多垃圾数据,何况我们在测试的时候有时候就需要制造一些垃圾数据(代码问题出现垃圾数据)
  • db_column数据库中的字段名,如果你觉得表的字段不容易理解,想改成更加容易理解的名称,就可以自定义model属性,使用db_column指定固定的字段名
  • related_name,这个不太好解释,就是外键关联表,可以通过该字段指定的名称查询这个表里的信息。当然是可以通过model的类名直接进行查询的,但类名一般都很长,一般情况下大家都会设置related_name。另外如果通过类名查询,切记类名需要全小写
  • managed表明该表是否是django迁移的表
  • app_label指明该表属于数据库的schema,即哪个库。一般我们都会链接多个数据库,通过该字段指定该表在哪个库里

业务说明

TbGroupBookingInfo是拼团的团信息,TbGroupBookingUser是团的成员信息,一对多,一个团可以有多个成员,通过group_booking_info_id字段关联TbGroupBookingInfo表中的主键id

Serializer

嵌套方案

from rest_framework import serializers

from soyoung.models import *


class TbGroupBookingInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = TbGroupBookingInfo
        fields = "__all__"


class TbGroupBookingUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = TbGroupBookingUser
        fields = "__all__"


class GroupBookingInfoSerializer(serializers.ModelSerializer):
    # related_name='booking_info',不能随便命名,必须是related_name指定的名称
    booking_info_bak = TbGroupBookingUserSerializer(many=True, souce='booking_info')

    class Meta:
        model = TbGroupBookingInfo
        fields = ['pid', 'booking_info_bak']


class GroupBookingUserSerializer(serializers.ModelSerializer):
    # 不需要重命名的时候可以简写,当然一般全量取名字应该在model中就已经定义好了
    # group_booking_info = TbGroupBookingInfoSerializer()
    # 这种写法不常用,group_booking_info外键的字段名
    group = TbGroupBookingInfoSerializer(source='group_booking_info')
    # 取关联表中的指定字段
    group_pid = serializers.IntegerField(source='group_booking_info.pid')
    group_uid = serializers.IntegerField(source='group_booking_info.uid')

    class Meta:
        model = TbGroupBookingUser
        fields = "__all__"

这个方案,其实就是model和serializer是一一对应的关系,有一个model就会有一个serializer。然后view使用的serializer再重新进行定义。

主表查询从表信息,字段名是从表related_name指定的名称,想重命名可以通过source指定

从表查询主表信息,字段名就是自己的外键字段名称,同样可以通过source进行重命名

需要特别留意的是,主表查询从表的时候,不可以像从表查询主表的时候直接查询属性信息,只能查询表里的所有信息

model自定义

class TbGroupBookingInfo(models.Model):
    product_group_booking_id = models.PositiveIntegerField()
    pid = models.PositiveIntegerField()
    status = models.PositiveIntegerField()
    end_date = models.DateTimeField()
    price_deposit = models.IntegerField()
    price_online = models.IntegerField()
    create_date = models.DateTimeField()
    uid = models.PositiveBigIntegerField()
    max_member_cnt = models.PositiveIntegerField()
    real_member_cnt = models.PositiveIntegerField()
    is_supplement_master = models.PositiveIntegerField()

    class Meta:
        managed = False
        db_table = 'tb_group_booking_info'
        verbose_name = '拼团团属性详情表'
        app_label = 'order'

    @property
    def users(self):
        queryset = self.booking_info.all()
        return [{"uid": query.uid} for query in queryset]

个人偏向使用该方法,这样可以自定义需要输出的字段,上面嵌套的方案,fields不知道如何进行指定。

PS:view分享一下,用于测试

class TbGroupBookingUserView(APIView):
    def get(self, request):
        queryset = TbGroupBookingUser.objects.all()[:10]
        serializer = GroupBookingUserSerializer(instance=queryset, many=True)
        return Response(data=serializer.data, status=status.HTTP_200_OK)


class TbGroupBookingInfoView(APIView):
    '''test'''

    def get(self, request):
        queryset = TbGroupBookingInfo.objects.all()[:10]
        serializer = GroupBookingInfoSerializer(instance=queryset, many=True)
        # print(serializer.data)
        return Response(data=serializer.data, status=status.HTTP_200_OK)

  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值