【问题标题】:How to filter ManyToManyField in serializer如何在序列化程序中过滤 ManyToManyField
【发布时间】:2021-11-20 23:18:26
【问题描述】:

在我的代码中,ServiceListSerializer(many=True, source='service_id') 给出了所有服务列表,而不是根据其类别提供的服务

我不知道如何从多对多字段中检索和过滤

这是我的代码:

模型.py

class Services(models.Model):
    service_id = models.AutoField(primary_key=True)
    parent_id = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True,related_name='sub_service')
    service_name = models.CharField(max_length=100)
    service_icon = models.CharField(max_length=500, null=True, blank=True)
    service_image = models.CharField(max_length=500, null=True, blank=True)
    service_description = models.CharField(max_length=5000, null=True, blank=True)
    category_id = models.ForeignKey(Category,on_delete=models.CASCADE)
    active_status = models.BooleanField(default=True)
    type = models.SmallIntegerField(blank=True, null=True)


class Variant(models.Model):
    variant_id = models.AutoField(primary_key=True)
    service_id = models.ManyToManyField(Services)
    category_id = models.ManyToManyField(Category)
    variant_name = models.CharField(max_length=100)
    variant_icon = models.CharField(max_length=1000, null=True, blank=True)
    variant_image = models.CharField(max_length=1000, null=True, blank=True)
    variant_description = models.CharField(max_length=5000, null=True, blank=True)
    active_status = models.BooleanField(default=True)

查看.py

class ServicesList(viewsets.ViewSet):

    def list(self, request):
        variant_id = request.data.get('variant_id')
        queryset = Category.objects.all()
        querysetSerializer = CategoryServiceListSerializer(queryset, many=True, context={'variant_id': variant_id})
        return Response({"status": 200, "message": "Success", "data": querysetSerializer.data})

序列化器.py

class CategoryServiceListSerializer(serializers.ModelSerializer):
    variant = serializers.SerializerMethodField()

    def get_variant(self, instance):
        variant_id = self.context.get('variant_id')
        if variant_id:
            variants = instance.variant_set.filter(pk=variant_id)
        else:
            variants = instance.variant_set.all()
        return VariantServiceSerializer(variants, many=True).data

    class Meta:
        fields = ("category_id", "category_name", "category_icon", "category_description", "variant")
        model = Category


class ServiceListSerializer(serializers.ModelSerializer):

    class Meta:
        model = Services
        fields = "__all__"

class VariantServiceSerializer(serializers.ModelSerializer):
    services = ServiceListSerializer(many=True, source='service_id')
    # services = serializers.SerializerMethodField()

    class Meta:
        model = Variant
        fields = "__all__"

    # def get_services(self, obj):
    #     print(obj.service_id)
    #     return obj

输出:

{
            "category_id": 1,                        # <
            "category_name": "category1",
            "variant": [
                {
                    "variant_id": 2,
                    "variant_name": "variant2",
                    "services": [
                        {
                            "service_id": 2,
                            "service_name": "service2",
                            "category_id": 1                
                        },
                        {
                            "service_id": 1,
                            "service_name": "service1",
                            "category_id": 1
                        },
                        {
                            "service_id": 1,
                            "service_name": "service1",
                            "category_id": 2                     #Category Not match with parent
                        }
                    ]
                }
            ]
        },
        {
            "category_id": 2,                        # <
            "category_name": "categoy2",
            "variant": [
                {
                    "variant_id": 2,
                    "variant_name": "variant2",
                    "services": [
                        {
                            "service_id": 2,
                            "service_name": "service2",
                            "category_id": 1                     #Category Not match with parent
                        },
                        {
                            "service_id": 1,
                            "service_name": "service1",
                            "category_id": 1                     #Category Not match with parent
                        },
                        {
                            "service_id": 1,
                            "service_name": "service1",
                            "category_id": 2
                        }
                    ]
                }
            ]
        },
        {
            "category_id": 3,                        # <
            "category_name": "category3",
            "variant": [
                {
                    "variant_id": 2,
                    "variant_name": "variant2",
                    "services": [
                        {
                            "service_id": 2,
                            "service_name": "service2",
                            "category_id": 1                     #Category Not match with parent
                        },
                        {
                            "service_id": 1,
                            "service_name": "service1",
                            "category_id": 1                     #Category Not match with parent
                        },
                        {
                            "service_id": 1,
                            "service_name": "service1",
                            "category_id": 2                     #Category Not match with parent
                        }
                    ]
                }
            ]
        }

预期输出:

{
            "category_id": 1,
            "category_name": "category1",
            "variant": [
                {
                    "variant_id": 2,
                    "variant_name": "variant2",
                    "services": [
                        {
                            "service_id": 2,
                            "service_name": "service2",
                            "category_id": 1
                        },
                        {
                            "service_id": 1,
                            "service_name": "service1",
                            "category_id": 1
                        }
                    ]
                }
            ]
        },
        {
            "category_id": 2,
            "category_name": "categoy2",
            "variant": [
                {
                    "variant_id": 2,
                    "variant_name": "variant2",
                    "services": [
                        {
                            "service_id": 1,
                            "service_name": "service1",
                            "category_id": 2
                        }
                    ]
                }
            ]
        },
        {
            "category_id": 3,
            "category_name": "category3",
            "variant": [
                {
                    "variant_id": 2,
                    "variant_name": "variant2",
                    "services": []
                }
            ]
        }

【问题讨论】:

    标签: django django-models django-rest-framework django-queryset


    【解决方案1】:

    尝试Prefetch变体的相关服务,并根据类别实例仅使用匹配的类别进行过滤,如下所示:

    class CategoryServiceListSerializer(serializers.ModelSerializer):
        variant = serializers.SerializerMethodField()
    
        def get_variant(self, instance):
            variant_id = self.context.get('variant_id')
            if variant_id:
                variants = instance.variant_set.filter(pk=variant_id)
            else:
                variants = instance.variant_set.all()
    
            variants = variants.prefetch_related(
                Prefetch(
                    'services'
                    queryset=Services.objects.filter(category_id=instance.category_id)
                )
            )
    
            return VariantServiceSerializer(variants, many=True).data
    

    【讨论】:

      猜你喜欢
      • 2021-02-17
      • 1970-01-01
      • 2019-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-26
      • 2015-03-25
      相关资源
      最近更新 更多