Django Rest Framework filters calculated model property

Sorry for the newbie question. I have the following model:

    class WeightSlip(models.Model):

        grossdate = models.DateTimeField(auto_now=False, auto_now_add=False)
        grossweight = models.DecimalField(max_digits=6, decimal_places=2, default=0)
        taredate = models.DateTimeField(auto_now=False, auto_now_add=False)
        tareweight = models.DecimalField(max_digits=6, decimal_places=2, default=0)
        vehicle = models.CharField(max_length=12)

        @property
        def netweight(self):
            return self.grossweight - self.tareweight

        @property
        def slipdate(self):
            if self.grossdate > self.taredate:
               return grossdate.date()
            else:
               return taredate.date()

Serializer:

    class WeightSlipSerializer(serializers.ModelSerializer):

       class Meta:
          model = models.WeightSlip
          fields = ('grossdate', 'grossweight', 'taredate', 'tareweight', 'slipdate', 'netweight', 'vehicle')
          read_only_fields = ('slipdate', 'netweight')

I am trying to use django-rest-framework-filters to filter the computed properties of 'netweight' and 'slipdate':

    class WeightSlipFilter(FilterSet):

       class Meta:
           model = WeightSlip
           fields = ('slipdate', 'netweight', 'vehicle')

This gives me an error:

TypeError: 'Meta.fields' contains fields that are not defined on this FilterSet: slipdate, netweight

Is there a workaround to this problem besides adding calculated fields to the database?

Thanks in advance.

+10
source share
2 answers

slipdate, netweight, db. F

from django.db.models import F, Case, When

class WeightSlipFilter(FilterSet):
    slipdate = DateTimeFilter(method='filter_slipdate')
    netweight = NumberFilter(method='filter_netweight')

    class Meta:
        model = WeightSlip
        fields = ('slipdate', 'netweight', 'vehicle')

    def filter_netweight(self, queryset, value):
        if value:
            queryset = queryset.annotate(netweight=F('grossweight') - F('tareweight')).filter(netweight=value)
        return queryset

    def filter_slipdate(self, queryset, value):
        if value:
            queryset = queryset.annotate(slipdate=Case(When(grossdate__gt=F('taredate'), then=F('grossdate')), default=F('taredate')).filter(slipdate=value)
        return queryset
+10

, django-, Filter.method 4 , :

def filter_slipdate(self, queryset, name, value):
    if value:
        queryset = queryset.annotate(slipdate=Case(When(grossdate__gt=F('taredate'), then=F('grossdate')), default=F('taredate')).filter(slipdate=value)
    return queryset

`` `

+2

Source: https://habr.com/ru/post/1657912/


All Articles