英文:
Filtering avg sum via OrderingFilter
问题
需要通过OrderingFilter来筛选avg(非模型)字段。
我的models.py
class Product(models.Model):
store = models.ForeignKey(Store, on_delete=models.CASCADE, null=True, verbose_name="store")
sku = models.CharField(max_length=255, blank=True, default="", verbose_name="SKU")
name = models.CharField(max_length=255, blank=True, default="", verbose_name="name")
class ProductInfo(models.Model):
default_related_name = "productinfo"
product = models.OneToOneField("Product", on_delete=models.CASCADE, null=True, verbose_name="product")
barcode = models.CharField(max_length=255, null=True, verbose_name="barcode")
price = models.DecimalField(max_digits=7, decimal_places=2, default=Decimal(0), verbose_name="price")
cost_price = models.DecimalField(max_digits=7, decimal_places=2, default=Decimal(0), verbose_name="cost price")
vat = models.DecimalField(max_digits=3, decimal_places=1, default=Decimal(0), verbose_name="% tax")
我通过OrderingFilter来筛选Product。
我的filters.py
from products.models import Product
from django_filters import OrderingFilter
from django_filters.rest_framework import FilterSet
class ProductFilter(FilterSet):
order_by_field = "ordering"
ordering = OrderingFilter(
fields=(
"name",
(("productinfo__price"), ("price")),
(("productinfo__barcode"), ("barcode")),
)
)
class Meta:
model = Product
我需要计算销售利润。这可以通过一个单独的函数或者使用注释来完成。
price-cost_price-taxes_sum=profit
但这个参数不是一个模型字段。我是否可以将它添加到过滤器中?目标是通过排序来获取利润更多的商品。
英文:
I need to filter avg (non-model) field via OrderingFilter.
My models.py
class Product(models.Model):
store = models.ForeignKey(Store, on_delete=models.CASCADE, null=True, verbose_name="store")
sku = models.CharField(max_length=255, blank=True, default="", verbose_name="SKU")
name = models.CharField(max_length=255, blank=True, default="", verbose_name="name")
class ProductInfo(models.Model):
default_related_name = "productinfo"
product = models.OneToOneField("Product", on_delete=models.CASCADE, null=True, verbose_name="product")
barcode = models.CharField(max_length=255, null=True, verbose_name="barcode")
price = models.DecimalField(max_digits=7, decimal_places=2, default=Decimal(0), verbose_name="price")
cost_price = models.DecimalField(max_digits=7, decimal_places=2, default=Decimal(0), verbose_name="cost price")
vat = models.DecimalField(max_digits=3, decimal_places=1, default=Decimal(0), verbose_name="% tax")
I filter Product via OrderingFilter
My filters.py
from products.models import Product
from django_filters import OrderingFilter
from django_filters.rest_framework import FilterSet
class ProductFilter(FilterSet):
order_by_field = "ordering"
ordering = OrderingFilter(
fields=(
"name",
(("productinfo__price"), ("price")),
(("productinfo__barcode"), ("barcode")),
)
)
class Meta:
model = Product
I need to calculate the profit from the sales. This can be done in a separate function or I can use an annotation.
price-cost_price-taxes_sum=profit
But this parameter is not a model field. Can I somehow add it to the filter? The goal is to get goods that bring more profit by sorting.
答案1
得分: 2
你可以像这样向你的过滤器集添加字段:
import django_filters
class ProductFilter(FilterSet):
profit = django_filters.CharFilter(method='profit_filter', label='profit')
class Meta:
model = Product
fields = [
'profit'
]
def profit(self, queryset, name, value):
return queryset.annotate().filter()
英文:
you can add fields to your filterset like this :
import django_filters
class ProductFilter(FilterSet):
profit = django_filters.CharFilter(method='profit_filter', label='profit')
class Meta:
model = Product
fields = [
'profit'
]
def profit(self, queryset, name, value):
return queryset.annotate().filter()
答案2
得分: 0
你可以使用F expressions在QuerySet中进行<code>profit</code>的注释,然后将其简单地添加到你的<code>filter</code>中。
<h4>一个例子:</h4>
views.py
from rest_framework.viewsets import ModelViewSet
from django.db.models import F
from myapp.models import Product
from myapp.filters import ProductFilter
from myapp.serializers import ProductSerializer
from django_filters import rest_framework as filters
class ProductViewSet(ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [filters.DjangoFilterBackend]
filterset_class = ProductFilter
def get_queryset(self):
qs = (
super()
.get_queryset()
.annotate(profit= F('productinfo__price') - F('productinfo__cost_price') - F('productinfo__vat'))
)
return qs
filters.py
from .models import Product
from django_filters import OrderingFilter
from django_filters.rest_framework import FilterSet
class ProductFilter(FilterSet):
order_by_field = "ordering"
ordering = OrderingFilter(
fields=(
("name", "name"),
("profit", "profit"),
("productinfo__price", "price"),
("productinfo__barcode", "barcode")
)
)
class Meta:
model = Product
fields = '__all__'
英文:
You can annotate the QuerySet with <code>profit</code> using <code>F expressions</code> and simply add it to your <code>filter</code>.
<h4>An example:</h4>
views.py
from rest_framework.viewsets import ModelViewSet
from django.db.models import F
from myapp.models import Product
from myapp.filters import ProductFilter
from myapp.serializers import ProductSerializer
from django_filters import rest_framework as filters
class ProductViewSet(ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [filters.DjangoFilterBackend]
filterset_class = ProductFilter
def get_queryset(self):
qs = (
super()
.get_queryset()
.annotate(profit=
F('productinfo__price') -
F('productinfo__cost_price') -
F('productinfo__vat')
)
)
return qs
filters.py
from .models import Product
from django_filters import OrderingFilter
from django_filters.rest_framework import FilterSet
class ProductFilter(FilterSet):
order_by_field = "ordering"
ordering = OrderingFilter(
fields=(
("name", "name"),
("profit", "profit"),
("productinfo__price", "price"),
("productinfo__barcode", "barcode")
)
)
class Meta:
model = Product
fields = '__all__'
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论