Django: django-tables2 pagination and filtering

后端 未结 1 1654
时光说笑
时光说笑 2020-12-20 19:07

I have a working table generated by django-tables2:

my_filter = TestFilter(request.POST) 
table = TestTable(TestObj.objects.all(), order_by=\"-my_date\")
Req         


        
1条回答
  •  礼貌的吻别
    2020-12-20 19:59

    Which version of django_tables2 are you using? I checked the source and saw that django_tables2 is using a template tag named querystring for creating the pagination links in the table.html template. the querystring tag updates the current url with the paging parameters. so django_tables2 supports pagination + filtering out of the box (that's what I remembered).

    Please try updating to the latest version of django_tables2 and make sure that you are using the default table.html template for rendering your tables.

    Also are you submitting your filter form with GET or POST? Please make sure that submit it with GET!

    Finally, please take a look at my answer to this question Django Tables - Column Filtering

    update: I took a closer look in the code you posted: first of all, you are passing post data to the filter: you cannot use POST for that, POST has to be used only for actions that modify your data. also I saw that you do not filter anything but instead you pass .all() to the table! where is the actual filtering done? you should pass the filtered data to the table as I describe in the answer above!

    update 2: The problem with your view is that when you first visit the page the GET dictionary does not contain the my_choice attribute so it will throw an exception when trying to access the my_choice attribute through the [] operator, so you should check to see if it actually exists using for instance .get(), something like this:

    my_filter = TestFilter(request.GET)
    my_choice = my_filter.data.get('my_choice') # This won't throw an exception
    if my_choice: # If my_choice existed on the GET dictionary this will return non-null value
        table = TestTable(TestObj.objects.filter(choice=my_choice), order_by="-my_date")
    else:
        table = TestTable(TestObj.objects.all(), order_by="-my_date")
    RequestConfig(request, paginate={"per_page": 10}).configure(table)
    return render(request, 'test_app/index.html', {'table': table, 'my_filter': my_filter})
    

    The above should work, however by doing do queryset filtering yourself - you are violating nearly every django design philosophy !

    That's why I told you to read my other answer to the similar question (Django Tables - Column Filtering) in which I recommend using django-filter which is a package explicitly used for filtering querysets. Please check the documentation or my answer to see how it can be used (I'd be happy to help if you have questions).

    Also, there is a number of other minor problems with your code:

    • You don't need to check if the request.method is GET - it will always be GET since you won't do any POSTs

    • You shouldn't include {{ csrf_token }} to your template - it is only needed for POST.

    • The TestFilter class is actually a Form that's why I recommend naming it TestFilterForm or something similar -- if you'd used django-filter then you'd create a FilterSet class which'd be named TestFilter. Correct naming of classes is very important, when I first saw your code I thought that the TestFilter class was a FilterSet and not a Form !

    0 讨论(0)
提交回复
热议问题