Django Rest Framework过滤计算的模型属性

Ama*_*dhu 10 django django-filter django-filters django-rest-framework

抱歉新手问题.我有以下型号:

    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()
Run Code Online (Sandbox Code Playgroud)

串行:

    class WeightSlipSerializer(serializers.ModelSerializer):

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

我正在尝试使用django-rest-framework-filters来过滤计算出的'netweight'和'slipdate'属性:

    class WeightSlipFilter(FilterSet):

       class Meta:
           model = WeightSlip
           fields = ('slipdate', 'netweight', 'vehicle')
Run Code Online (Sandbox Code Playgroud)

这给了我一个错误:

TypeError: 'Meta.fields' contains fields that are not defined on this FilterSet: slipdate, netweight
Run Code Online (Sandbox Code Playgroud)

除了将计算字段添加到数据库之外,是否有解决此问题的方法?

提前致谢.

Dim*_*osh 11

您可以为其创建自定义过滤器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
Run Code Online (Sandbox Code Playgroud)

  • 从 django_filters.rest_framework 导入(NumberFilter,DateTimeFilter,) (2认同)