简体   繁体   中英

Django filter out on related field

I have three models, two of them linked to the third by a foreign key, as follows:

class A(models.Model):
    sku = models.ForeignKey("SKU", on_delete=models.PROTECT)
    production_start = models.DateField(blank=True, null=True)
    production_end = models.DateField(blank=True, null=True)

class B(models.Model):
    date = models.DateField()
    sku = models.ForeignKey("SKU", on_delete=models.PROTECT)
    quantity = models.PositiveIntegerField()
    last_modified = models.DateTimeField(auto_now=True)

class SKU(models.Model):
    product = models.CharField(max_length=64)
    design = models.CharField(max_length=64)

I would like to filter the foreign keys that can be returned in the A response in an efficient way, such that by defining a date range filter on the endpoint parameters (eg, /A/?from_date=2021-01-01&to_date=2021-01-02), for all elements of A whose production dates fall within the range, I want it to return the object A containing the elements of B for the same SKU whose date matches the specific dates.

Example:

"data"=[
    {
        "sku": 7,
        "production_start": "2021-01-01",
        "production_end": "2021-01-07",
        "b": [
            {
                "date": "2021-01-01",
                "quantity": 100
            },
            {
                "date": "2021-01-02",
                "quantity": 200
            }
        ]
    },
    ...
]

So far I've tried adding a filter from django-filters to my views.py .

class AViewSet(viewsets.ReadOnlyModelViewSet):
    class AFilterSet(django_filters.FilterSet):
        from_date = django_filters.DateFilter(field_name="sku__b__date", lookup_expr="gte")
        to_date = django_filters.DateFilter(field_name="sku__b__date", lookup_expr="lte")

        class Meta:
            model = models.A
            fields = []


    queryset = models.A.objects.all()
    serializer_class = serializers.ASerializer
    filterset_class = AFilterSet

And my serializers.py :

class BSerializer(serializers.Serializer):
    date = serializers.DateField()
    quantity = serializers.IntegerField()


class ASerializer(serializers.ModelSerializer):
    b = BSerializer(many=True, source="sku.b_set")

    class Meta(ASerializer.Meta):
        fields = "__all__"

However, this approach is still returning every object B related to object A , instead of filtering out the dates outside of range filter.

Add variable depth in class Meta following the follows, reference :

class AccountSerializer(serializers.ModelSerializer):
    class Meta:
        model = Account
        fields = ['id', 'account_name', 'users', 'created']
        depth = 1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM