首页 > 解决方案 > How do I fitler the intial table using django-tables2 and django-filter?

问题描述

I'm using django-tables2 and django-filter to list employees from a model. I'm having trouble filtering the initial table rendered. It's including all records. I want the initial table to only include employees where status=1. Then, have the filter take over.

views.py

from .models import Employee
from .tables import EmployeeTable
from .filters import EmployeeFilter
from .forms import EmployeeSearchForm

class EmployeeListView(SingleTableMixin, FilterView):
    model = Employee
    table_class = EmployeeTable
    template_name = 'employees/employee_list.html'

    filterset_class = EmployeeFilter

    def get_table_data(self):
        return Employee.objects.filter(status=1)

filters.py:

from django.db.models import Value, Q
from django import forms

from .models import Employee

class EmployeeFilter(django_filters.FilterSet):
    search = django_filters.CharFilter(label='Search', method='search_filter')
    inactive = django_filters.BooleanFilter(widget=forms.CheckboxInput, label='Inactive', method='include_inactive')
    
    def search_filter(self, queryset, name, value):
        return queryset.annotate(fullname=Concat('first_name', Value(' '), 'last_name')).filter(
                Q(fullname__icontains=value) | Q(g_number__icontains=value)
            )

    def include_inactive(self, queryset, name, value):
        expression = Q(status__in=[1,2,5]) if value else Q(status__in=[1,5])
        return queryset.filter(expression)
    
    class Meta:
        model = Employee
        fields = ['search', 'inactive']

tables.py:

from django.utils.html import format_html
from django.urls import reverse

import django_tables2 as tables

from .models import Employee

class EmployeeTable(tables.Table):
    full_name = tables.Column(order_by=("first_name", "last_name"))
    g_number = tables.Column(linkify=True)
    selection = tables.columns.CheckBoxColumn(
            accessor='pk', 
            attrs = { "th__input": {"onclick": "toggle(this)"}},
            orderable=False
        )
    term = tables.Column(verbose_name=("Action"), empty_values=())

    class Meta:
        model = Employee
        
        template_name = "django_tables2/bootstrap.html"
        fields = ("selection", "g_number","full_name", 'org', 'job', 'status', 'term')
        attrs = {
            "class": "table table-hover",
            "thead": {"class": "thead-dark"}
        }
        order_by = '-g_number'

标签: pythondjangodjango-filterdjango-tables2

解决方案


从 Django 过滤器文档中,您可以过滤过滤器类上的主要查询集。更新:要根据 self.request 中的属性设置 qs,只需检查该属性并进行相应过滤。

https://django-filter.readthedocs.io/en/master/guide/usage.html#filtering-the-primary-qs

class EmployeeFilter(django_filters.FilterSet):

    [...]       

    @property
    def qs(self):
        parent = super().qs
        filter_inactive = getattr(self.request, 'inactive', False)

        if not filter_inactive:
            return parent.filter(status=1)

        return parent

推荐阅读