Ich begann mit django-tables2 (was ich aus dem ersten Eindruck sehr empfehlen kann) und ich frage mich, wie man Spaltenfilterung implementieren. Ich finde nicht die passende Dokumentation dafür, aber ich bin sicher, dass es irgendwo da draußen ist.Django Tabellen - Spaltenfilterung
Antwort
Eine kleine späte Antwort, aber trotzdem ... Ich konnte auch keine geeignete Dokumentation für die Spaltenfilterung finden. Es gibt viele Methoden, es zu tun:
A. Mit der Hand: Ich mache so etwas wie dies ich ein Formular hinzufügen, die Felder enthält, würde ich mit filtern mag und dann meiner Meinung nach:
data = models.MyClass.all() form = forms.MyFilterForm(request.GET) if request.GET.get('field1'): data = data.filter(field1=request.GET.get('field1')) if request.GET.get('field2'): data = data.filter(field2=request.GET.get('field2')) ... table = tables.MyTable(data)
Das funktioniert sehr gut, aber es ist nicht so trocken, weil es in der Ansicht hart codiert ist.
B. Mit einem SingleTableView: Eine andere Möglichkeit, eine SingleTableView hinzuzufügen ist, der die Form enthält:
from django_tables2 import SingleTableView class FilteredSingleTableView(SingleTableView): def get_table_data(self): data= models.MyClass.objects.all if self.request.GET.get('field1'): data = data.filter(field1=self.request.GET.get('field1')) if self.request.GET.get('field1'): data = data.filter(field1=self.request.GET.get('field1')) return data def get_context_data(self, **kwargs): context = super(FilteredSingleTableView, self).get_context_data(**kwargs) context['form'] = forms.MyFilterForm(self.request.user, self.request.GET) return context
Das ist mehr DRY :)
C. Mit SingleTableView und django_filters: Dies ist wahrscheinlich die trockenste Art und Weise :) Hier ist, wie es geht:
Definieren Sie zuerst einen Filter:
class MyFilter(django_filters.FilterSet): field1 = django_filters.CharFilter() field2 = django_filters.CharFilter() ...
(oder Sie können in Meta (Modell = MyModel)
Erstellen Sie jetzt einen SingleTableView wie diese
class FilteredSingleTableView(SingleTableView): def get_table_data(self): f = filters.MyFilter(self.request.GET, queryset =models.MyClass.objects.all() , request=self.request) return f def get_context_data(self, **kwargs): context = super(FilteredSingleTableView, self).get_context_data(**kwargs) f = filters.MyFilter(self.request.GET, queryset =models.MyClass.objects.all() , request=self.request) context['form'] = f.form return context
(wahrscheinlich ein Modell Filter hinzufügen, dass es ein Problem mit der Linie f = ... aber ich konnte es nicht anders machen.
Schließlich können Sie die SingleTableView von Ihrem urls.py wie diese
url(r'^$', views.FilteredSingleTableView.as_view( table_class = tables.MyTable, model=models.MyClass, template_name ='mytemplate.html', table_pagination={ "per_page":50 })) , name='filtered_single_table_view' ),
D. rufen eine generische Klasse verwenden: Dies ist ein noch DRY und django-generic-Klasse-Ansichten wie Art und Weise ! Dies ist tatsächlich der nächste Schritt von C: Sie Ihre FilteredSingleTableView wie folgt erklären:
class FilteredSingleTableView(django_tables2.SingleTableView): filter_class = None def get_table_data(self): self.filter = self.filter_class(self.request.GET, queryset =super(FilteredSingleTableView, self).get_table_data()) return self.filter.qs def get_context_data(self, **kwargs): context = super(FilteredSingleTableView, self).get_context_data(**kwargs) context['filter'] = self.filter return context
Nun ist die FilteredSingleTableView einen Parameter für die Klasse des Filters, so dass Sie es in Ihrem urls.py unter den anderen passieren kann Parameter:
url(r'^$', ships.views.FilteredSingleTableView.as_view( model=models.MyModel, table_class=tables.MyTable, template_name='mytemplate.html' , filter_class = filters.MyFilter, ) , name='myview'),
So können Sie FilteredSingleTableView ohne Modifikationen für die Filterung Ihrer Modelle verwenden !!
Beachten Sie auch, dass ich jetzt den Filter als Instanzvariable gespeichert und entfernt, um den sich wiederholenden Code f=filters.MyFilter(...)
, die ich in hatte C (get_table_data vor get_context_data genannt wird - wenn das nicht immer der Fall war, dann könnten wir ein hinzufügen get_filter
Instanzmethode, die den Trick tun würde)!
-Update 23/04/2016: Nach dem großen Nachfrage, ich habe ein einfaches Django-Projekt erstellt, das die allgemeine FilteredSingleTableView Klasse verwendet eine Tabelle der Bücher zu filtern. Sie können es herausfinden: https://github.com/spapas/django_table_filtering
aktualisieren 2016.05.07: Bitte beachten Sie, dass Sie return self.filter.qs
für die get_table_data
Rückkehr in D (I aktualisiert haben alread damit die Antwort) verwenden sollten, oder aber die Ansicht wird zu lange dauern, große Tische zu machen - weitere Informationen finden Sie auf https://github.com/spapas/django_table_filtering/issues/1
finden Es ist ein einfacher und Dryer Weg, um eine allgemeine Ansicht dies tun zu bauen:
from django_filters.views import FilterView
from django_tables2 import SingleTableView
class FilterTableView(FilterView, SingleTableView):
def get_table_data(self):
return self.object_list
So können Sie dies tun :
class MyTableView(FilterTableView):
model = MyModel
table_class = MyTable
filterset_class = MyFilter
Wenn Sie lieber django_tables2.views.SingleTableMixin
im Konzert verwenden, um mit Djangos ListView
oder eine Unterklasse davon (statt SingleTableView
) Ich schlage vor, die folgenden:
class FilteredListViewMixin(object):
""" Uses django-filter to filter a ListView. """
filter_class = None
def get_queryset(self):
qs = super(FilteredListViewMixin, self).get_queryset()
self.filter = self.filter_class(self.request.GET,
queryset=qs)
return self.filter.qs
def get_context_data(self, **kwargs):
context = super(FilteredListViewMixin, self).get_context_data(**kwargs)
context['filter'] = self.filter
return context
Es hat den zusätzlichen Vorteil, nicht gekoppelt ist django-tables2
(DRY FTW) bedeutet, dass es mit generischen ListViews
auch verwendet werden kann.