Django 过滤问题

Issue with Django filtering

我的代码有问题,我不知道如何解决!我使用 Django Filters 和 Django Tables 2 从 db table 构建可过滤列表。过滤器本身工作正常,但我发现如果我将所有过滤器留空,我会在网页上得到整个 table,而在这种情况下我想要零结果。

非常欢迎任何建议/建议!

查看下面的代码:

tables.py

from .models import Casualty

import django_tables2 as tables
from django_tables2 import TemplateColumn
from django_tables2.utils import A

class CasualtyTable(tables.Table):

    edit = TemplateColumn(template_name='casualties_update_column.html', verbose_name='')
    delete = TemplateColumn(template_name='casualties_delete_column.html', verbose_name='')

    def before_render(self, request):
        if request.user.has_perm('casualty.change_bar'):
            self.columns.show('edit')
        else:
            self.columns.hide('edit')

        if request.user.has_perm('casualty.delete_bar'):
            self.columns.show('delete')
        else:
            self.columns.hide('delete')

    class Meta:
        model = Casualty
        exclude = ('author', 'added_by', 'updated_by', 'date_created', 'date_updated')
        attrs = {"class": "casualties" , "style": "overflow-x:auto;"}
filters.py

import django_filters

from .models import Casualty

class CasualtyFilter(django_filters.FilterSet):
    first_name = django_filters.CharFilter(label = 'First Name', lookup_expr='contains')
    last_name = django_filters.CharFilter(label = 'Last Name', lookup_expr='contains')
    middle_name = django_filters.CharFilter(label = 'Middle Name', lookup_expr='contains')
    ref_nr = django_filters.CharFilter(label = 'Ref Nr', lookup_expr='contains')
    service_nr = django_filters.CharFilter(label = 'Service Nr', lookup_expr='contains')
    rank = django_filters.CharFilter(label = 'Rank', lookup_expr='contains')
    regiment = django_filters.CharFilter(label = 'Regiment', lookup_expr='contains')
    how_they_died = django_filters.CharFilter(label = 'How Died', lookup_expr='contains')
    date_of_death = django_filters.CharFilter(label = 'Date of Death', lookup_expr='contains')
    age_at_death = django_filters.CharFilter(label = 'Age of Death', lookup_expr='contains')
    place_of_death = django_filters.CharFilter(label = 'Place of Death', lookup_expr='contains')
    street_address = django_filters.CharFilter(label = 'Street', lookup_expr='contains')
    area = django_filters.CharFilter(label = 'Area', lookup_expr='contains')
    relations = django_filters.CharFilter(label = 'Relations', lookup_expr='contains')
    notes = django_filters.CharFilter(label = 'Notes', lookup_expr='contains')
    awards = django_filters.CharFilter(label = 'Awards', lookup_expr='contains')
    local_memorial_or_source = django_filters.CharFilter(label = 'Memorial / Source', lookup_expr='contains')
    occupation_before_war = django_filters.CharFilter(label = 'Occupation before War', lookup_expr='contains')

    class Meta:
        model = Casualty
        paginate_by = 50
        exclude = ['id', 'added_by', 'updated_by', 'date_created', 'date_updated']

    def __init__(self, *args, **kwargs):
        super(CasualtyFilter, self).__init__(*args, **kwargs)
        # at sturtup user doen't push Submit button, and QueryDict (in data) is empty
        if self.data == {}:
            self.queryset = self.queryset.none()
views.py:

from django_filters.views import FilterView
from django_tables2.views import SingleTableMixin
from django_tables2.export.views import ExportMixin

from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.views.generic import TemplateView

from django.urls import reverse_lazy

from .models import Casualty
from .tables import CasualtyTable
from .filters import CasualtyFilter

class FilteredCasualtyListView(ExportMixin, SingleTableMixin, FilterView):
    table_class = CasualtyTable
    model = Casualty
    template_name = 'casualty_list.html'
    filterset_class = CasualtyFilter
template:

{% extends 'base.html' %}
{% load static %}

{% block extrahead %}
  <link rel="stylesheet" href="{% static 'css/casualties.css' %}">
  <style>
    input {max-width: 8em; max-height: 2em};
  </style>
{% endblock %}

{% load django_tables2 %}
{% load bootstrap4 %}

{% load crispy_forms_tags %}

{% block title %} WWI Casualties {% endblock title %}

{% block content %}
  <div class="filters">
      <form action="" method="get" class="filterform">
          <div class="form-row justify-content-md-center">
            <div class="col-md-auto">
              {{ filter.form.ref_nr|as_crispy_field }}
            </div>
            <div class="col-md-auto">
              {{ filter.form.last_name|as_crispy_field }}
            </div>
            <div class="col-md-auto">
              {{ filter.form.first_name|as_crispy_field }}
            </div>
            <div class="col-md-auto">
              {{ filter.form.middle_name|as_crispy_field }}
            </div>
            <div class="col-md-auto">
              {{ filter.form.service_nr|as_crispy_field }}
            </div>
            <div class="col-md-auto">
              {{ filter.form.rank|as_crispy_field }}
            </div>
            <div class="col-md-auto">
              {{ filter.form.regiment|as_crispy_field }}
            </div>
            <div class="col-md-auto">
              {{ filter.form.how_they_died|as_crispy_field }}
            </div>
            <div class="col-md-auto">
              {{ filter.form.date_of_death|as_crispy_field }}
            </div>
          </div>

          <div class="border-top my-3"></div>

          <div class="form-row justify-content-md-center">
            <div class="col-md-auto">
              {{ filter.form.age_at_death|as_crispy_field }}
            </div>
            <div class="col-md-auto">
              {{ filter.form.place_of_death|as_crispy_field }}
            </div>
            <div class="col-md-auto">
              {{ filter.form.street_address|as_crispy_field }}
            </div>
            <div class="col-md-auto">
              {{ filter.form.area|as_crispy_field }}
            </div>
            <div class="col-md-auto">
              {{ filter.form.relations|as_crispy_field }}
            </div>
            <div class="col-md-auto">
              {{ filter.form.notes|as_crispy_field }}
            </div>
            <div class="col-md-auto">
              {{ filter.form.awards|as_crispy_field }}
            </div>
            <div class="col-md-auto">
              {{ filter.form.local_memorial_or_source|as_crispy_field }}
            </div>
            <div class="col-md-auto">
              {{ filter.form.occupation_before_war|as_crispy_field }}
            </div>
          </div>

          <div class="border-top my-3"></div>

          <div class="form-row justify-content-md-center">
            <button type="submit" class="btn btn-primary">Search</button>
            <a href="{% url 'casualty_list' %}" class="btn btn-info" role="button">Clear Search</a>
          </div>
      </form>
  </div>
  {% render_table table %}

{% endblock content %}

昨晚整理,在 filters.py 中添加 属性。我检查是否至少填充了 filterset dict 的一个值。如果不是这样,我return一个空查询集

filters.py 

import django_filters

from .models import Casualty

class CasualtyFilter(django_filters.FilterSet):
    first_name = django_filters.CharFilter(label = 'First Name', lookup_expr='contains')
    last_name = django_filters.CharFilter(label = 'Last Name', lookup_expr='contains')
    middle_name = django_filters.CharFilter(label = 'Middle Name', lookup_expr='contains')
    ref_nr = django_filters.CharFilter(label = 'Ref Nr', lookup_expr='contains')
    service_nr = django_filters.CharFilter(label = 'Service Nr', lookup_expr='contains')
    rank = django_filters.CharFilter(label = 'Rank', lookup_expr='contains')
    regiment = django_filters.CharFilter(label = 'Regiment', lookup_expr='contains')
    how_they_died = django_filters.CharFilter(label = 'How Died', lookup_expr='contains')
    date_of_death = django_filters.CharFilter(label = 'Date of Death', lookup_expr='contains')
    age_at_death = django_filters.CharFilter(label = 'Age of Death', lookup_expr='contains')
    place_of_death = django_filters.CharFilter(label = 'Place of Death', lookup_expr='contains')
    street_address = django_filters.CharFilter(label = 'Street', lookup_expr='contains')
    area = django_filters.CharFilter(label = 'Area', lookup_expr='contains')
    relations = django_filters.CharFilter(label = 'Relations', lookup_expr='contains')
    notes = django_filters.CharFilter(label = 'Notes', lookup_expr='contains')
    awards = django_filters.CharFilter(label = 'Awards', lookup_expr='contains')
    local_memorial_or_source = django_filters.CharFilter(label = 'Memorial / Source', lookup_expr='contains')
    occupation_before_war = django_filters.CharFilter(label = 'Occupation before War', lookup_expr='contains')

    class Meta:
        model = Casualty
        exclude = ['id', 'added_by', 'updated_by', 'date_created', 'date_updated']

    def __init__(self, *args, **kwargs):
        super(CasualtyFilter, self).__init__(*args, **kwargs)
        # at sturtup user doen't push Submit button, and QueryDict (in data) is empty
        if self.data == {}:
            self.queryset = self.queryset.none()

    @property
    def qs(self):
        queryset = super(CasualtyFilter, self).qs

        has_filter = any(field for field in self.data.values())

        if not has_filter:
            queryset = queryset.none()

        return queryset