views:

394

answers:

3

I'm using Django Forms to do a filtered/faceted search via POST, and I would like to Django's paginator class to organize the results. How do I preserve the original request when passing the client between the various pages? In other words, it seems that I lose the POST data as soon as I pass the GET request for another page back to my views. I've seen some recommendations to use AJAX to refresh only the results block of the page, but I'm wondering if there is a Django-native mechanism for doing this.

Thanks.

A: 

You can ask request object if it's ajax, simply request.is_ajax. This way you can detect, whether it's first post request or further questions about the next pages.

gruszczy
+4  A: 

If you want to access the store data in later request, you would have to store it somewhere. Django provides several ways to archive this:

1) You can use sessions to store the query: Every visitor who visits your site will get an empty session object and you can store whatever you want inside this object, which acts like a dict. Drawback: A single visitor can't do multiple searches with pagination concurrently.

2) Use cookies: If you set a cookie which is stored on the client side, the browser will append the data of the cookie to each request where you can access it. Cookies are more server friendly, because you don't need a session manager for them on the server, but the data stored in cookies is visible (and editable) to the client. Drawback: same as before.

3) Use hidden fields: You can add a form with some hidden fields on your search-result page and store the query inside them. Then, the client will resend the query whenever you submit the form. Drawback: You must use a form with submit buttons for the pagination on your page (simple links wont work).

4) Create Links which contain the query: Instead of using POST, you can also use GET. For example, you could have a link like "/search/hello+world/?order=votes" and "paginated links" like "/search/hello+world/2/?order-votes". Then the query can be easily retrieved from the URL. Drawback: The maximum amount of data you can send via GET is limited (But that shouldn't be a problem for a simple search).

5) Use a combination: You might want to store all the data in a session or a database and access them via a generated key which you can put in the URL. URLs might then look like "/search/029af239ccd23/2" (for the 2nd page) and you can use the key to access a huge amount of data which you have stored before. This eliminates the drawback of solution 1 as well as that of solution 4. New drawback: much work :)

6) Use AJAX: With ajax you can store the data inside some js-variables on the client side, which can then passed to the other requests. And since ajax will only update your result list, the variables aren't getting lost.

tux21b
Thanks, this is helpful. Just to unpack this question a little more: is this the intended use for the paginator class? My view processes the initial search form, then sends the template the paginator.page() object for the first page. The results list is generated from the object_list for that page. It seems odd that I couldn't send it the entire search result set, and somehow page through it without resubmitting the search for every page. If that is the intended use for the class, I can work with it. Just want to make sure I'm not missing something obvious. Thanks!
andyashton
Yes, that is the intended use. Don't forget that Django is a web framework, and by their nature web requests are not stateful. So if you want to keep state, you'll have to store it somewhere - and tux21b has given you some options as to where.
Daniel Roseman
Very helpful, thank you both.
andyashton
A: 

Have the search form and the results display on one single django template. Initially, use css to hide the results display area. On POSTing the form, you could check to see if the search returned any results and hide the search form with css if results exist. If results do not exist, use css to hide the results display area like before. In your pagination links, use javascript to submit the form, this could be as simple as document.forms[0].submit(); return false;

You will need to handle how to pass the page number to django's paging engine.

chefsmart