英文:
How add non model field to django filters
问题
I have a view with pagination and filtering that displays a list of products. I would like to provide the user with the option to choose between displaying all the products they can buy or displaying only the products they have already purchased.
show_products.py
def show_products(previously_purchased, user):
if previously_purchased:
transactions = Transaction.objects.filter(user_id=user).values_list('product_id')
return Product.objects.filter(pk__in=[q[0] for q in transactions])
return Product.objects.all()
models.py
class Product(models.Model):
name = models.CharField(max_length=255)
...
views.py
class ProductList(ListView):
...
def dispatch(self, request, *args, **kwargs):
return super(ProductList, self).dispatch(request, *args, **kwargs)
def get_queryset(self):
self.filterset = ProductFilter(
self.request.GET,
queryset=show_products(previously_purchased=) # show_products(previously_purchased=show_)
)
return self.filterset.qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['form'] = self.filterset.form
context['products'] = show_products(previously_purchased=)
return context
filters.py
class ProductFilter(django_filters.FilterSet):
CHOICE = {
('True', 'previously purchased'),
('False', 'all')
}
name = django_filters.CharFilter()
class Meta:
model = Product
fields = ['name']
The show_products(previously_purchased=)
function is responsible for creating a queryset of all products or only previously purchased ones, using the previously_purchased
parameter.
Unfortunately, when I add previously_purchased
in ProductFilter
, I get an error saying that the previously_purchased
field does not exist in the Product
model.
When I add @property
in the Product
model, and intercept self.request.GET['previously_purchased']
to change the show_products()
parameter, the display works fine. But the pagination stops working.
英文:
I have a view with pagination and filtering that displays a list of products. I would like to provide the user with the option to choose between displaying all the products they can buy or displaying only the products they have already purchased.
show_products.py
def show_products(previously_purchased, user):
if previously_purchased:
transactions = Transaction.objects.filter(user_id=user).values_list('product_id')
return Product.objects.filter(pk__in=[q[0] for q in transactions])
return Product.objects.all()
models.py
class Product(models.Model):
name = models.CharField(max_length=255)
...
views.py
class ProductList(ListView):
...
def dispatch(self, request, *args, **kwargs):
return super(ProductList, self).dispatch(request, *args, **kwargs)
def get_queryset(self):
# show_ = True if 'previously_purchased' in self.request.GET and self.request.GET['previously_purchased'] == 'True' else False
self.filterset = ProductFilter(
self.request.GET,
queryset=show_products(previously_purchased=) # show_products(previously_purchased=show_)
)
return self.filterset.qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['form'] = self.filterset.form
context['products'] = show_products(previously_purchased=)
return context
filters.py
class ProductFilter(django_filters.FilterSet):
CHOICE = {
('True', 'previously purchased'),
('False', 'all')
}
name = django_filters.CharFilter()
# previously_purchased = django_filters.ChoiceFilter(choices=CHOICE)
class Meta:
model = Product
fields = ['name']
The show_products(previously_purchased=)
function is responsible for creating a queryset of all products or only previously purchased ones, using the previously_purchased
parameter.
Unfortunately, when I add previously_purchased
in ProductFilter
, I get an error saying that the previously_purchased
field does not exist in the Product
model.
When I add @property
in the Product
model, and intercept self.request.GET['previously_purchased']
to change the show_products()
parameter, the display works fine. But the pagination stops working.
答案1
得分: 1
以下是您要翻译的内容:
在 django-filter
中,您可以在字段内指定名为 method
的关键字参数,该参数接受可调用对象或方法的名称,因此您可以像这样修改您的 ProductFilter
:
class ProductFilter(django_filters.FilterSet):
CHOICE = {
('True', 'previously purchased'),
('False', 'all')
}
name = django_filters.CharFilter()
previously_purchased = django_filters.ChoiceFilter(
choices=CHOICE,
method='filter_previously_purchased',
)
def filter_previously_purchased(self, queryset, name, value):
if value == 'True':
transactions = Transaction.objects.filter(user_id=self.request.user).values_list('product_id')
queryset = queryset.filter(pk__in=[q[0] for q in transactions])
return queryset
class Meta:
model = Product
fields = ['name', 'previously_purchased',]
在上述代码中,我已将您的 show_products()
逻辑添加到 filter_previously_purchased
函数中,该函数接受以下参数:
queryset
这是指定的model
的查询集,例如Product.objects.all()
name
这是字段名称,例如previously_purchased
value
这是来自客户端的值。
英文:
In django-filter
you can specify keyword argument named as method
inside field which accepts either a callable or the name of a method so you camodify you ProductFilter
like this
class ProductFilter(django_filters.FilterSet):
CHOICE = {
('True', 'previously purchased'),
('False', 'all')
}
name = django_filters.CharFilter()
previously_purchased = django_filters.ChoiceFilter(
choices=CHOICE,
method='filter_previously_purchased',
)
def filter_previously_purchased(self, queryset, name, value):
if value == 'True':
transactions = Transaction.objects.filter(user_id=self.request.user).values_list('product_id')
queryset = queryset.filter(pk__in=[q[0] for q in transactions])
return queryset
class Meta:
model = Product
fields = ['name', 'previously_purchased',]
In above code I've added your show_products()
logic inside filter_previously_purchased
function with which takes these arguments
queryset
It is queryset of specifiedmodel
eg.Product.objects.all()
name
it's a field name eg.previously_purchased
value
it's value which comes from client.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论