web-dev-qa-db-ja.com

Django RestFrameworkフィルタリング計算モデルプロパティ

初心者の質問でごめんなさい。私は次のモデルを持っています:

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()

シリアライザー:

class WeightSlipSerializer(serializers.ModelSerializer):

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

Django-rest-framework-filters を使用して、計算された「netweight」プロパティと「slipdate」プロパティをフィルタリングしようとしています。

class WeightSlipFilter(FilterSet):

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

これは私にエラーを与えます:

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

計算フィールドをデータベースに追加する以外に、この問題の回避策はありますか?

前もって感謝します。

12
Aman Sandhu

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
Dima Kudosh

Django-filterの最新バージョンを使用している場合は、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
Clarity