2012-11-28 10 views

Antwort

23

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

3

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 
0

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.