<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>muhuk.com &#187; pagination</title>
	<atom:link href="http://www.muhuk.com/tag/pagination/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.muhuk.com</link>
	<description>know thyself</description>
	<lastBuildDate>Thu, 02 Sep 2010 07:13:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>A Civilized Way Display Lots Of Data</title>
		<link>http://www.muhuk.com/2009/08/a-civilized-way-display-lots-of-data/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=a-civilized-way-display-lots-of-data</link>
		<comments>http://www.muhuk.com/2009/08/a-civilized-way-display-lots-of-data/#comments</comments>
		<pubDate>Mon, 31 Aug 2009 08:05:18 +0000</pubDate>
		<dc:creator>Atamert Ölçgen</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[pagination]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[template]]></category>

		<guid isPermaLink="false">http://www.muhuk.com/?p=274</guid>
		<description><![CDATA[Django is a civilized way to build web applications. Pagination is a civilized way to display lots of data. There are still people developing websites with tens of thousands of items crammed in a single page. Even if you use JavaScript to paginate client-side, never ending download results in poor user experience. Django has pagination [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.djangoproject.com">Django</a> is a civilized way to build web applications. Pagination is a civilized way to display lots of data. There are still people developing websites with tens of thousands of items crammed in a single page. Even if you use JavaScript to paginate client-side, never ending download results in poor user experience.</p>

<p>Django has <a href="http://docs.djangoproject.com/en/dev/topics/pagination/">pagination</a> support built-in. All you need to do is to wrap your <code>QuerySet</code> with <code>django.core.paginator.Paginator</code> and add <code>paginator.page(some_page_number)</code> to your template context. Then you can use attributes/methods such as <code>has_next</code> and <code>num_pages</code> or iterate over <code>page_range</code> to display your pagination navigation. To access items in current page you can use <code>object_list</code>, which is in fact a <code>QuerySet</code> sliced with correct limits. That also means; only those items that you want to display are queried. It&#8217;s all <a href="http://docs.djangoproject.com/en/dev/topics/pagination/">documented well</a> as usual.</p>

<h3>Django-pagination Takes It One Step Further</h3>

<p>In my opinion pagination belongs to presentation. If you have many queries/views to paginate, you might find yourself repetitively writing pagination code. You can move all your pagination code into the template with <a href="http://code.google.com/p/django-pagination/">django-pagination</a>. This is accomplished with a middleware and a set of template tags.</p>

<p>With django-pagination you can paginate your results like this:</p>

<pre><code>{% autopaginate object_list %}

{% for object in object_list %}
  {{ object }}
{% endfor %}

{% paginate %}
</code></pre>

<p><code>autopaginate</code> tag replaces your <code>QuerySet</code> with a paginator and <code>paginate</code> tag renders <code>pagination/pagination.html</code> template with correct values.</p>

<p>You can download django-pagination from <a href="http://code.google.com/p/django-pagination/downloads/list">Google Code</a>, but appereantly development is moved to <a href="http://github.com/ericflo/django-pagination/tree/master">GitHub</a>. I wish there was a message left on the Google Code page.</p>

<h3>A Little SEO Shouldn&#8217;t Hurt</h3>

<p>When you have a paginated view, you usually display the results of the first page if the pagination variable is missing. As a result <code>/some_view/</code> and <code>/some_view/?page=1</code> return identical responses. This might be interpreted by search engines as a duplicate. My solution for this is to redirect the first page to the page without a page variable:</p>

<pre><span style="color:#555555">   1 </span><span style="color:#000000; font-weight:bold">from</span> django<span style="color:#000000">.</span>http <span style="color:#000000; font-weight:bold">import</span> HttpResponsePermanentRedirect
<span style="color:#555555">   2 </span><span style="color:#000000; font-weight:bold">from</span> pagination<span style="color:#000000">.</span>middleware <span style="color:#000000; font-weight:bold">import</span> PaginationMiddleware
<span style="color:#555555">   3 </span>
<span style="color:#555555">   4 </span><span style="color:#000000; font-weight:bold">class</span> <span style="color:#010181">SEOPaginationMiddleware</span><span style="color:#000000">(</span>PaginationMiddleware<span style="color:#000000">):</span>
<span style="color:#555555">   5 </span>    <span style="color:#000000; font-weight:bold">def</span> <span style="color:#010181">process_request</span><span style="color:#000000">(</span>self<span style="color:#000000">,</span> request<span style="color:#000000">):</span>
<span style="color:#555555">   6 </span>        <span style="color:#000000; font-weight:bold">if</span> request<span style="color:#000000">.</span>method <span style="color:#000000">==</span> <span style="color:#ff0000">'GET'</span><span style="color:#000000">:</span>
<span style="color:#555555">   7 </span>            <span style="color:#000000; font-weight:bold">try</span><span style="color:#000000">:</span>
<span style="color:#555555">   8 </span>                page <span style="color:#000000">=</span> <span style="color:#830000">int</span><span style="color:#000000">(</span>request<span style="color:#000000">.</span>GET<span style="color:#000000">[</span><span style="color:#ff0000">'page'</span><span style="color:#000000">])</span>
<span style="color:#555555">   9 </span>            <span style="color:#000000; font-weight:bold">except</span> <span style="color:#000000">(</span><span style="color:#000000; font-weight:bold">KeyError</span><span style="color:#000000">,</span> <span style="color:#000000; font-weight:bold">ValueError</span><span style="color:#000000">,</span> <span style="color:#000000; font-weight:bold">TypeError</span><span style="color:#000000">):</span>
<span style="color:#555555">  10 </span>                page <span style="color:#000000">=</span> <span style="color:#000000; font-weight:bold">None</span>
<span style="color:#555555">  11 </span>            <span style="color:#000000; font-weight:bold">if</span> page <span style="color:#000000">==</span> <span style="color:#2928ff">1</span><span style="color:#000000">:</span>
<span style="color:#555555">  12 </span>                params <span style="color:#000000">=</span> request<span style="color:#000000">.</span>GET<span style="color:#000000">.</span><span style="color:#010181">copy</span><span style="color:#000000">()</span>
<span style="color:#555555">  13 </span>                <span style="color:#000000; font-weight:bold">del</span><span style="color:#000000">(</span>params<span style="color:#000000">[</span><span style="color:#ff0000">'page'</span><span style="color:#000000">])</span>
<span style="color:#555555">  14 </span>                path <span style="color:#000000">=</span> request<span style="color:#000000">.</span>path
<span style="color:#555555">  15 </span>                <span style="color:#000000; font-weight:bold">if</span> params<span style="color:#000000">:</span>
<span style="color:#555555">  16 </span>                    path <span style="color:#000000">+=</span> <span style="color:#ff0000">'?'</span> <span style="color:#000000">+</span> params<span style="color:#000000">.</span><span style="color:#010181">urlencode</span><span style="color:#000000">()</span>
<span style="color:#555555">  17 </span>                <span style="color:#000000; font-weight:bold">return</span> <span style="color:#010181">HttpResponsePermanentRedirect</span><span style="color:#000000">(</span>path<span style="color:#000000">)</span>
<span style="color:#555555">  18 </span>        <span style="color:#000000; font-weight:bold">return</span> <span style="color:#830000">super</span><span style="color:#000000">(</span>SEOPaginationMiddleware<span style="color:#000000">,</span> self<span style="color:#000000">).</span><span style="color:#010181">process_request</span><span style="color:#000000">(</span>request<span style="color:#000000">)</span>
</pre>

<p>This works only if your page variable is an URL parameter (i.e. you are using <code>GET</code>).</p>


<p>Related posts:<ol><li><a href='http://www.muhuk.com/2009/09/django-fixtures/' rel='bookmark' title='Permanent Link: Django Fixtures'>Django Fixtures</a></li>
<li><a href='http://www.muhuk.com/2009/10/new-project-telvee/' rel='bookmark' title='Permanent Link: New Project: Telvee'>New Project: Telvee</a></li>
<li><a href='http://www.muhuk.com/2010/01/developing-reusable-django-apps/' rel='bookmark' title='Permanent Link: Developing Reusable Django Apps'>Developing Reusable Django Apps</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.muhuk.com/2009/08/a-civilized-way-display-lots-of-data/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
