How to filter ModelSelect2Widget queryset with a request data?
kabrachups opened this issue · comments
I use django_tables2 with django_filter according to django_tables2 tutorial:
#views.py
from django_filters.views import FilterView
from django_tables2.views import SingleTableMixin
class FilteredCarListView(SingleTableMixin, FilterView):
table_class = CarTable
model = Car
template_name = 'template.html'
filterset_class = CarFilter
def get_queryset(self):
return self.model.objects.filter(owner_id=request.user.id)
And now I want to have a filter's field and its ModelSelect2Widget with the same filter as in get_queryset() above. Something like this:
queryset = Car.objects.filter(owner_id=request.user.id).
For filter's field I've found this decision (I guess it is not DRY):
# filters.py
from .models import Car
from django_select2.forms import ModelSelect2Widget
def get_cars(request):
return Car.objects.filter(owner_id=request.user.id)
class CarFilter(django_filters.FilterSet):
car = django_filters.ModelChoiceFilter(
queryset = get_cars,
field_name='car',
widget = ModelSelect2Widget(
model = Car,
queryset = Car.objects.filter(owner_id=request.user.id)
search_fields=['car__icontains'])
But how to limit choises in ModelSelect2Widget to display current user's cars only?
Hi @kabrachups
Thanks for reaching out. You are already on a good track. I haven't used django_tables2
before, but I believe the following code should work:
import django_filters
from django_select2 import forms as select2
from . import models
class CarWidget(select2.ModelSelect2Widget):
queryset = models.Car.objects.all()
def filter_queryset(self, request, **kwargs):
"""
Limit results to Car's owned by the current user.
If the current user is not authenticated, return empty queryset.
"""
if not request.user.is_authenticated:
return super().filter_queryset(request, **kwargs).filter(
owner_id=request.user.id
)
return self.queryset.none()
class CarField(django_filters.ModelChoiceFilter):
widget = CarWidget
def get_queryset(self, request):
"""
Limit results to Car's owned by the current user.
If the current user is not authenticated, return empty queryset.
"""
if request.user.is_authenticated:
return models.Car.objects.filter(owner_id=request.user.id)
return models.Car.objects.none()
class CarFilter(django_filters.FilterSet):
car = django_filters.ModelChoiceFilter(
widget=CarWidget,
)
Let me know if that works for you and if you have any further questions.
Best
-Joe
It does work! )))
Just one simple correction:
.filter_queryset(request, **kwargs)
to
.filter_queryset(request, term, queryset, **kwargs)
Thank you a LOT!
Perfect, happy it worked :)
Sorry to reopen this, but I'm trying to set-up full text search using a TrigramSimilarity class. Here's how I'd do it from the command line:
from django.contrib.postgres.search import TrigramSimilarity
term = 'John Smith'
Author.objects.annotate(
similarity=TrigramSimilarity("name", term), # `name` is the model field name, `term` is the search term.
).filter(
similarity__gt=0.3,
).order_by("-similarity")
I tried following the pattern above, but it required asearch_fields
parameter in the s2forms.ModelSelect2Widget
Class, which overrode everything else.
I'm afraid I'm not too good at Class inheritance; I'm trying to cargo-cult what you've got here and it simply isn't working... :-)