0

I'm fairly new to Class Based Views and I have a problem.

I implemented get_queryset to return all my users (for testing) and they are returned and pagination works fine (outside get_queryset, I do have "paginate_by" field set).

A user can then search some specific users via POST and the end of post method is:

return render(request, self.template_name, {'objects': some_users})

It works fine, but pagination is lost. What am I doing wrong?

dnmh
  • 2,045
  • 2
  • 34
  • 49

2 Answers2

1

The pagination is done in paginate_queryset, called by get_context_data, called by post (that defaults to a subcall to get) , so you can so something like (given you have a filter method that filters based on post data):

def post(self, request, *args, **kwargs):
    self.queryset = self.filter(self.get_queryset())
    return super(MyView, self).get(request, *args, **kwargs)

the parent post will call get_queryset, that returns your filtered self.queryset, and it will paginate it when calling get_context_data

to not display the queryset on the first get,

def get(self, request, *args, **kwargs):
    return self.self.response_class(
        request=self.request,
        template=self.get_template_names())

the pagination template link should always post to the view instead of the default get so save the search input in the context and change the template for the pagination, with

def get_context_data(self, **kwargs):
     context = super(MyView, self).get_context_data(**kwargs)
     context['search_value'] = self.request.POST.get('search_name', None)
     return context

,

<form action="?page={{ page_obj.previous_page_number }}" method="post">
    {% csrf_token %}
    <input type="hidden" value="{{ search_value }}" name="search_name">
    <button type="submit">&laquo;</button>
</form>

and for the next link:

<form action="?page={{ page_obj.next_page_number }}" method="post">
    {% csrf_token %}
    <input type="hidden" value="{{ search_value }}" name="search_name">
    <button type="submit">&raquo;</button>
</form>
DRC
  • 4,898
  • 2
  • 21
  • 35
  • Looks promising. I've tried it and got "'super' object has no attribute 'post'". I've copy/pasted your stuff and changed the view name. It extends ListView, don't know if that matters. – dnmh Dec 02 '14 at 22:06
  • @dnmh sorry I had it wrong, ListView inherits get from View and has no post method! I've modified the answer. – DRC Dec 02 '14 at 22:11
  • 1
    Great, it's fine now! :) Thanks! – dnmh Dec 02 '14 at 22:13
  • I also removed my implementation of get_queryset (which was only for testing). But now I get all items rendered on first load, instead just on search. Is there a way of preventing that? – dnmh Dec 02 '14 at 22:15
  • Plus, new problem.. when I go to search results at page 2, search is lost and all items are displayed again :-( – dnmh Dec 02 '14 at 22:18
  • you should post to page 2... how is the url fragment when going to page >1 using get? – DRC Dec 02 '14 at 22:20
  • I have a querystring ?page=# which is just a GET. This is in the template: next – dnmh Dec 02 '14 at 22:22
  • @dnmh edited again for the two issues, also it works if requesting the page directly with a page. – DRC Dec 02 '14 at 22:25
  • 'MyView' object has no attribute 'object_list'. Any ideas? – dnmh Dec 02 '14 at 22:31
1

I've used session in order to do this stuff. Now I'm able to do a search by using POST and the pagination is working fine

def MySearch(request):
if request.method == 'POST':
    search_text = request.POST.get('search_string')
    request.session['search'] = search_text
    query_set = MyModel.objects.filter(myattribute__icontains=search_text)
    paginator = Paginator(search, 1)
    page = request.GET.get('page')
    search = paginator.get_page(page)
    return render(request, 'myapp/mytemplate.html', {'page_obj': search})

if request.method == 'GET':
    if 'search' in request.session:
        query_set = MyModel.objects.filter(myattribute__icontains=search_text)
        paginator = Paginator(search, 1)
        page = request.GET.get('page')
        search = paginator.get_page(page)
        return render(request, 'myapp/mytemplate.html', {'page_obj': search})
    else:
        return render(request, 'myapp/mytemplate.html')
Tajinder Singh
  • 1,361
  • 2
  • 14
  • 26