2012-11-28 36 views
10

Tôi bắt đầu sử dụng django-tables2 (mà tôi có thể đánh giá cao từ ấn tượng đầu tiên) và tôi tự hỏi mình cách triển khai lọc cột. Tôi không tìm thấy tài liệu thích hợp cho nó, nhưng tôi chắc chắn nó là một nơi nào đó trên mạng.Bàn Django - Lọc cột

Trả lời

23

Câu trả lời hơi muộn nhưng dù sao ... Tôi cũng không thể tìm thấy bất kỳ tài liệu thích hợp nào để lọc cột. Có rất nhiều phương pháp để làm điều đó:

A. Bằng tay: Tôi thêm một hình thức có chứa các lĩnh vực Tôi muốn lọc với và sau đó tôi làm điều gì đó như thế này trong quan điểm của tôi:

 
    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) 

Điều này hoạt động rất tốt đẹp tuy nhiên nó không phải như vậy DRY vì nó là khó mã hóa trong xem.

B. Sử dụng một SingleTableView: Một cách khác là thêm một SingleTableView có chứa các hình thức:

 
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 

Đây là DRY hơn :)

C. Sử dụng SingleTableView và django_filters: Đây có lẽ là cách DRY nhất :) Dưới đây là cách thực hiện:

Đầu tiên xác định bộ lọc:

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

(hoặc bạn có thể thêm một bộ lọc mô hình trong Meta (model = MyModel)

Bây giờ, tạo một SingleTableView như thế này

 
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 

(có thể có một vấn đề với dòng f = ... nhưng tôi không thể làm nó hoạt động được.

Cuối cùng, bạn có thể gọi SingleTableView từ urls.py bạn như thế này

 
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. Sử dụng một lớp generic: Đây là một thậm chí khô và nhiều hơn nữa django-generic-đẳng cấp quan điểm như cách ! Đây thực sự là bước tiếp theo từ C: Chỉ cần tuyên bố FilteredSingleTableView của bạn như thế này:

 
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 

Bây giờ FilteredSingleTableView có một tham số cho lớp của bộ lọc, do đó bạn có thể vượt qua nó trong urls.py của bạn trong số các khác thông số:

 
    url(r'^$', ships.views.FilteredSingleTableView.as_view(
     model=models.MyModel, 
     table_class=tables.MyTable, 
     template_name='mytemplate.html' , 
     filter_class = filters.MyFilter, 
    ) , name='myview'), 

Vì vậy, bạn có thể sử dụng FilteredSingleTableView mà không sửa đổi để lọc bất kỳ mô hình nào của bạn !!

Cũng cần chú ý rằng bây giờ tôi đã lưu các bộ lọc như là một biến dụ và loại bỏ mã lặp đi lặp lại f=filters.MyFilter(...) mà tôi đã có trong C (get_table_data được gọi trước khi get_context_data - nếu đó không phải luôn luôn như vậy thì chúng ta có thể thêm một get_filter phương pháp thể hiện sẽ thực hiện thủ thuật)!

Cập nhật 23/04/2016: Sau khi yêu cầu phổ biến, tôi đã tạo một dự án Django đơn giản sử dụng lớp FilteredSingleTableView chung để lọc một bảng sách. Bạn có thể tìm thấy nó ra tại địa chỉ: https://github.com/spapas/django_table_filtering

Cập nhật 2016/05/07: Xin lưu ý rằng bạn nên sử dụng return self.filter.qs cho get_table_data trở lại trong D (Tôi đã alread cập nhật câu trả lời với điều này) hoặc người nào khác xem sẽ mất quá nhiều thời gian để làm cho các bảng lớn - biết thêm có thể được tìm thấy trên https://github.com/spapas/django_table_filtering/issues/1

3

có một cách dễ dàng hơn và máy sấy để xây dựng một cái nhìn tổng quát làm điều này:

from django_filters.views import FilterView 
from django_tables2 import SingleTableView 


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

vì vậy, bạn có thể làm điều này :

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

Nếu bạn thích sử dụng django_tables2.views.SingleTableMixin phối hợp với Django ListView hoặc một lớp con của chúng (chứ không phải là SingleTableView) Tôi đề nghị như sau:

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 

Nó có lợi ích bổ sung không được cùng với django-tables2 (DRY FTW) có nghĩa là nó có thể được sử dụng chung với ListViews.