2012-11-28 15 views

risposta

23

Una risposta un po 'tardiva, ma comunque ... Non sono riuscito a trovare alcuna documentazione appropriata per il filtraggio delle colonne. Ci sono molti metodi per farlo:

A. A mano: aggiungo un modulo contenente i campi vorrei filtrare con e poi faccio qualcosa di simile a mio avviso:

 
    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) 

Questo funziona molto bene, tuttavia non è così SECCO perché è codificato in modo rigido nella vista.

B. Utilizzando una SingleTableView: Un altro modo è quello di aggiungere un SingleTableView che contiene il modulo:

 
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 

Questo è più DRY :)

C. Utilizzo SingleTableView e django_filters: Questo probabilmente è il modo più SECCO :) Ecco come procedere:

Prima definire un filtro:

 
class MyFilter(django_filters.FilterSet): 
    field1 = django_filters.CharFilter() 
    field2 = django_filters.CharFilter() 
... 

(o si può aggiungere un filtro modello a Meta (modello = MyModel)

Ora, creare una SingleTableView come questo

 
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 

(probabilmente c'è un problema con la linea f = ... ma non potrei farlo funzionare diversamente.

Infine, è possibile chiamare il SingleTableView dal urls.py come questo

 
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. Utilizzo di una classe generica: Si tratta di un ancora più asciutto e django-generic-class-vista come modo ! Questo è in realtà il passo successivo da C: Basta dichiarare il vostro FilteredSingleTableView in questo modo:

 
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 

Ora il FilteredSingleTableView ha un parametro per la classe del filtro in modo si può passare nella tua urls.py tra l'altro parametri:

Quindi è possibile utilizzare FilteredSingleTableView senza modifiche per il filtro di uno dei modelli !!

Si noti anche che ora ho salvato il filtro come una variabile di istanza e rimosso il codice ripetitivo f=filters.MyFilter(...) che avevo in C (get_table_data viene chiamato prima get_context_data - se non fosse sempre il caso, allora si potrebbe aggiungere un get_filter metodo di istanza che farebbe il trucco)!

Aggiornamento 23/04/2016: Dopo grande richiesta, ho creato un semplice progetto Django che utilizza la classe FilteredSingleTableView generica per filtrare una tabella di libri. Si possono trovare fuori a: https://github.com/spapas/django_table_filtering

Aggiornamento 2016/05/07: Si prega di notare che si dovrebbe usare per la return self.filter.qsget_table_data ritorno in D (ho alread aggiornato la risposta con questo) oppure il vista ci vorrà troppo tempo per il rendering di grandi tavoli - maggiori informazioni sono disponibili sul https://github.com/spapas/django_table_filtering/issues/1

3

C'è un modo più semplice e asciugatrice per costruire una visione generica fare questo:

from django_filters.views import FilterView 
from django_tables2 import SingleTableView 


class FilterTableView(FilterView, SingleTableView): 
    def get_table_data(self): 
     return self.object_list 

modo da poter fare questo :

class MyTableView(FilterTableView): 
    model = MyModel 
    table_class = MyTable 
    filterset_class = MyFilter 
0

Se si preferisce utilizzare django_tables2.views.SingleTableMixin di concerto con Django di ListView o una sottoclasse di esso (piuttosto che SingleTableView) suggerisco il seguente:

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 

Esso ha il vantaggio di non essere accoppiato ad django-tables2 (DRY FTW) significa che può essere utilizzato anche con il generico ListViews.