Jekson
Jekson

Reputation: 3262

Django get_queryset filtering with multiple select

I doing a form of filtering by the foreignkey field with two search conditions: OR and AND and multiple choices.

forms.py

class EmployeeSkillFilter(forms.ModelForm):
    skills = forms.ModelMultipleChoiceField(queryset=Technology.objects.all(), )

    class Meta:
        model = Employee
        fields = ['skills']

templates.py

<form  method="get" enctype="multipart/form-data">
     {% csrf_token %}
    <input type="checkbox" name="and" value="AND"> Choice and<br>
    <input type="checkbox" name="or" value="OR"> Choice OR<br>

          {{ skill_filter }}
    <button  type="submit" class="btn btn-info" type="button">Go!</button>
</form>

views.py

class AccountList(AuthorizedMixin, ListView):

    model = Employee
    template_name = 'employee_list.html'

    def get_queryset(self, *args, **kwargs):
        condition_and = self.request.GET.get('and', None)
        condition_or = self.request.GET.get('or', None)
        skill = self.request.GET.get('skills', None)
        if condition_and and skill:
            object_list = self.model.objects.filter(skills__name_id=skill) ??????

        if condition_or and tech:
            object_list = self.model.objects.filter(
                Q(skills__name_id=skill) |
                Q(skills__name_id=skill)
            ) ?????
        else:
            object_list = self.model.objects.all()

My urls looks like

localhost://....or=OR&skills=5&skills=4&skills=3

The problem is that when I select multiple objects in a form, I don't know how to pass them all to the condition

skills__name_id=skill 

Upvotes: 1

Views: 5315

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476567

Use the __in lookup [Django-doc] lookup, and in case of and logic, count the number of matches:

from django.db.models import Count

class AccountList(AuthorizedMixin, ListView):

    model = Employee
    template_name = 'employee_list.html'

    def get_queryset(self, *args, **kwargs):
        condition_and = self.request.GET.get('and', None)
        condition_or = self.request.GET.get('and', None)
        skills = self.request.GET.getlist('skills')
        if condition_and:
            object_list = self.model.objects.filter(
                skills__in=skills
            ).annotate(
                nskills=Count('skills')
            ).filter(
                nskills=len(skills)
            )
        elif condition_or:
            object_list = self.model.objects.filter(
                skills__in=skills
            ).distinct()
        else:
            object_list = self.model.objects.all()

Upvotes: 1

Related Questions