drf 自关联序列化

自关联的表如何序列化:
表:

class Category(BaseModel):
    """
    商品类别
    """
    CLASSIFY_CHOICES = (
        (1, '面料'),
        (2, "款式"),
    )
    name = models.CharField(max_length=20, verbose_name='名称')
    parent = models.ForeignKey('self', null=True, blank=True, related_name='subs', on_delete=models.SET_NULL, verbose_name='父类别')
    classify = models.SmallIntegerField(default=1, choices=CLASSIFY_CHOICES, verbose_name='所属商品分类')
    desc = models.CharField(default='', max_length=200, verbose_name='备注')

    class Meta:
        db_table = 'tb_category'
        verbose_name = '面料类别'
        verbose_name_plural = verbose_name

    def __str__(self):
        return '%s-%s-%s' % (self.id,self.get_classify_display(),self.name)

视图:

class AView(GenericAPIView):
    permission_classes = [IsAuthenticated, AdminUserPermission]
    
    def get(self, request, *args, **kwargs):
        query = Category.objects.filter(classify=1, parent_id__isnull=True).order_by('id')
        serializer = ASerializer(query, many=True)

        
        return APIResponse.success(data=serializer.data)

序列化器:

class ASerializer(serializers.ModelSerializer):
    subs = serializers.SerializerMethodField()

    class Meta:
        model = Category
        fields = ('id', 'name', 'parent_id', 'parent', 'subs')

    def get_subs(self, obj):
        if obj.subs:
            return ASerializer(obj.subs, many=True).data
        else:
            return None

但是这种有一个缺点,就是有多少条数据就查询多少次数据库,所以不建议数据特别多的使用,最好先把数据给查询出来,然后再排列组合就像下面的一样:
视图:

def change_comments(data, parent_id):
    """
    data: 序列化后的数据
    parent_id: 数据库中自关联的字段
    """
    list = []
    tree = {}
    root = ''
    p_id = ''

    for data_dict in data:
        #将data循环,然后加入一个dict中,key为每条数据的ID,val对应为整条数据
        tree[data_dict["id"]] = data_dict


    for data_dict in data:
        if data_dict[parent_id] == None:
            root = tree[data_dict["id"]]  #i.di为tree里的key,将key对应的val取出
            list.append(root)
        else:
            p_id = data_dict[parent_id]
            # 判断父级是否有孩子字段(childlist),如果有将当前数据加入,如果没有添加(childlist)后再加入
            if "sub" not in tree[p_id]:
                tree[p_id]['sub'] = []
            tree[p_id]["sub"].append(tree[data_dict["id"]])

    return list


class AView(GenericAPIView):
    permission_classes = [IsAuthenticated, AdminUserPermission]

    def get(self, request, *args, **kwargs):
        query = Category.objects.filter(classify=1).order_by('id')
        serializer = ASerializer(query, many=True)

        data = change_comments(serializer.data, 'parent_id')
        return APIResponse.success(data=data)

序列化器:

class ASerializer(serializers.ModelSerializer):
   
    class Meta:
        model = Category
        fields = ('id', 'name', 'parent_id', 'parent')

你可能感兴趣的:(Django)