<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us"><title>Django Advent Articles</title><link href="http://djangoadvent.com/feed/" rel="alternate" /><id>http://djangoadvent.com/feed/</id><updated>2010-03-05T00:00:00-11:00</updated><subtitle>Article feed for djangoadvent.com</subtitle><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/DjangoAdventArticles" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="djangoadventarticles" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry><title>Small Things</title><link href="http://djangoadvent.com/1.2/small-things/" rel="alternate" /><updated>2010-03-05T00:00:00-11:00</updated><author><name>Jacob Kaplan-Moss</name><uri>http://jacobian.org/</uri></author><id>http://djangoadvent.com/1.2/small-things/</id><summary type="html">&lt;div class="section" id="size-doesn-t-matter"&gt;
&lt;h1&gt;Size doesn't matter&lt;/h1&gt;
&lt;p&gt;Throughout the advent, we've been covering some of the big &lt;a class="reference external" href="http://djangoadvent.com/1.2/multiple-database-support/"&gt;new&lt;/a&gt; &lt;a class="reference external" href="http://djangoadvent.com/1.2/messages-rest-us/"&gt;features&lt;/a&gt; in Django
1.2. Those are all awesome, of course, but some of my favorites parts of Django
1.2 aren't big. There's a bunch of really sweet little improvements that taken
together really add up.&lt;/p&gt;
&lt;p&gt;Here are some of my favorites:&lt;/p&gt;
&lt;div class="section" id="email-backends"&gt;
&lt;h2&gt;Email backends&lt;/h2&gt;
&lt;p&gt;Django 1.2 gives you complete control over &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/email/#topic-email-backends"&gt;how Django sends email&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Django ships with a handful of standard backends, including the default SMTP
backend and backends that log emails to files, the console, or memory.&lt;/p&gt;
&lt;p&gt;We added this feature primarily to support those running Django on sandboxed
hosting environments like Google's &lt;a class="reference external" href="http://code.google.com/appengine/"&gt;App Engine&lt;/a&gt;, but I think it'll prove useful
in a bunch of other situations.&lt;/p&gt;
&lt;p&gt;The API's very simple: an email backend is a class that implements a handful of
methods:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;send_messages(email_messages)&lt;/tt&gt;, which sends a list of &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/email/#django.core.mail.EmailMessage"&gt;EmailMessage&lt;/a&gt;
objects.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;open()&lt;/tt&gt; (optional), which starts an e-mail-sending connection.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;close()&lt;/tt&gt; (optional), which closes the current connection.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;For example, you could easily redirect email to a RESTful API with something
like the following (which uses the &lt;a class="reference external" href="http://code.google.com/p/httplib2/"&gt;httplib2&lt;/a&gt; library):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;httplib2&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.conf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.utils&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;simplejson&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HttpPostEmailBackend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_messages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;httplib2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Http&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c"&gt;# Convert the list of messages to JSON to posting&lt;/span&gt;
        &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;simplejson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__dict__&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;content-type&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;application/json&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EMAIL_TARGET_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;POST&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c"&gt;# In Real Life we&amp;#39;d have error handling here &amp;#8212; the request could&lt;/span&gt;
        &lt;span class="c"&gt;# fail or time out. That&amp;#39;s left as an exercise for the reader.&lt;/span&gt;

        &lt;span class="c"&gt;# Return the number of successfully sent messages.&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then just wire it up in your settings file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;EMAIL_BACKEND&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;path.to.HttpPostEmailBackend&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;EMAIL_TARGET_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;http://example.com/email&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="read-only-admin-fields"&gt;
&lt;h2&gt;Read-only admin fields&lt;/h2&gt;
&lt;p&gt;You can now make fields read-only in the admin with the &lt;tt class="docutils literal"&gt;readonly_fields&lt;/tt&gt;
option:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PersonAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelAdmin&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;readonly_fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;age&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These fields will show up in the admin on the add/change pages, but won't be
editable. I see this being most useful when used with fields containing
calculated data, or other such de-normalized information.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="smarter-if-tag"&gt;
&lt;h2&gt;Smarter if tag&lt;/h2&gt;
&lt;p&gt;Designers and template developers, this one's for you:&lt;/p&gt;
&lt;p&gt;One of Django's core design philosophies is that &lt;a class="reference external" href="http://docs.djangoproject.com/en/1.1/misc/design-philosophies/#don-t-invent-a-programming-language"&gt;template languages shouldn't
try to be programming languages&lt;/a&gt;. To that end, we've kept the template
language deliberately simplisitic so that you'd be more or less forced to push
advanced logic up into the view.&lt;/p&gt;
&lt;p&gt;It's a delicate line, though, and over the years it's become clear that the
&lt;tt class="docutils literal"&gt;if&lt;/tt&gt; tag took &amp;quot;simplicity&amp;quot; a bit too far. Thus, Django 1.2's &lt;tt class="docutils literal"&gt;if&lt;/tt&gt; tag
has been made much more powerful. It now supports comparison operators, meaning
you can do things like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;user.username&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;jacob&amp;quot;&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
  ...
&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;endif&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;

&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;driver.bac&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;0.8&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
  ...
&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;endif&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;

&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;athlete&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;team.roster&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
  ...
&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;endif&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The tag supports &lt;tt class="docutils literal"&gt;==&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;!=&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&amp;lt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&amp;gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&amp;lt;=&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&amp;gt;=&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;in&lt;/tt&gt;, all of
which work like their Python equivalents. You can chain logic together with
&lt;tt class="docutils literal"&gt;and&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;or&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;not&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;This means that &lt;tt class="docutils literal"&gt;ifequal&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;ifnotequal&lt;/tt&gt; are no longer necessary, though
they're still available for backwards compatibility.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="css-classes-on-required-erroneous-form-rows"&gt;
&lt;h2&gt;CSS classes on required/erroneous form rows&lt;/h2&gt;
&lt;p&gt;It's pretty common to style form rows and fields that are required or have
errors. For example, you might want to present required form rows in bold and
highlight errors in red.&lt;/p&gt;
&lt;p&gt;Django 1.2 now makes it easy to add &lt;tt class="docutils literal"&gt;class&lt;/tt&gt; attributes to the generated HTML
for form fields and rows; you can then use CSS to style them accordingly. You'll
specify these class names in your form definitions:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ContactForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;error_css_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;error&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;required_css_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;required&amp;#39;&lt;/span&gt;

    &lt;span class="c"&gt;# ... and the rest of your fields here.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This'll make the generated HTML contain &lt;tt class="docutils literal"&gt;error&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;required&lt;/tt&gt; classes as
necessary. That is, if you use &lt;tt class="docutils literal"&gt;{{ form.as_table }}&lt;/tt&gt;, the generated HTML might
look something like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;required&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;th&amp;gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;id_subject&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Subject:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt; ... &lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;required&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;th&amp;gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;id_message&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Message:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt; ... &lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;required error&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;th&amp;gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;id_sender&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Sender:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt; ... &lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;id_cc_myself&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Cc myself:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt; ... &lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And you can then target those rows in CSS:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="nc"&gt;.required&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;font-weight&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="nc"&gt;.error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="cached-template-loading"&gt;
&lt;h2&gt;Cached template loading&lt;/h2&gt;
&lt;p&gt;Quick, pop quiz:&lt;/p&gt;
&lt;p&gt;Given these settings:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;app1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;app2&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;TEMPLATE_DIRS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;/dir1/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;/dir2/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and this line of code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;render_to_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;example.html&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and an &lt;tt class="docutils literal"&gt;example.html&lt;/tt&gt; containing:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nv"&gt;base.html&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;

&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;block&lt;/span&gt; &lt;span class="nv"&gt;content&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt; Hi! &lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;endblock&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;what's the worst-case number of many disk operations Django must perform to
render the response?&lt;/p&gt;
&lt;p&gt;...&lt;/p&gt;
&lt;p&gt;The answer's &lt;em&gt;eight&lt;/em&gt;. Why?&lt;/p&gt;
&lt;p&gt;Well, Django has to find &lt;tt class="docutils literal"&gt;example.html&lt;/tt&gt;. To do so, it'll consult the &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types"&gt;template
loaders&lt;/a&gt;. By default, these will first look in each application's directory
for the template, and then in each of the &lt;tt class="docutils literal"&gt;TEMPLATE_DIRS&lt;/tt&gt;. So, to find
&lt;tt class="docutils literal"&gt;example.html&lt;/tt&gt;, Django will try to load:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&amp;lt;app1's &lt;span class="pre"&gt;path&amp;gt;/templates/example.html&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&amp;lt;app2's &lt;span class="pre"&gt;path&amp;gt;/templates/example.html&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;/dir1/example.html&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;/dir2/example.html&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Next, because &lt;tt class="docutils literal"&gt;example.html&lt;/tt&gt; uses inheritance, Django must repeat the exercise
for &lt;tt class="docutils literal"&gt;base.html&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;These disk accesses are fairly cheap, but &lt;em&gt;not&lt;/em&gt; free. As sites group, you'll
have many more applications, more template directories, and probably more
complex template inheritance. It's not unusual to see a single template load
operation force over 100 disk I/O requests.&lt;/p&gt;
&lt;p&gt;Yuck.&lt;/p&gt;
&lt;p&gt;To help mitigate this problem, Django 1.2 now ships with a cached template
loader. This wraps existing template loaders, so unknown templates are looked up
normally. However, once the template's been found, the cached loader stores the
compiled template in memory, returning it directly for subsequent requests for
the same template. That is, each subsequent request doesn't even need to touch
the disk.&lt;/p&gt;
&lt;p&gt;To enable the cached template loader, you'll put something like this in your
settings:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;TEMPLATE_LOADERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;django.template.loaders.cached.Loader&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;&amp;#39;django.template.loaders.filesystem.Loader&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;&amp;#39;django.template.loaders.app_directories.Loader&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you've got other custom template loaders you can add 'em to the inner list
and they'll be wrapped by the cached loader as well.&lt;/p&gt;
&lt;div class="warning"&gt;
&lt;p class="first admonition-title"&gt;Warning&lt;/p&gt;
&lt;p class="last"&gt;All of the built-in Django template tags are safe to use with the cached
loader, but if you're using custom template tags that come from third party
packages, or that you wrote yourself, you'll need to &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#template-tag-thread-safety"&gt;ensure that the
implementation for each tag is thread-safe&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="et-cetera"&gt;
&lt;h2&gt;Et cetera&lt;/h2&gt;
&lt;p&gt;These are just my favorite small changes coming in Django 1.2. There are many
other small improvements, including:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;A new &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.BigIntegerField"&gt;big integer field&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/ref/django-admin/#syntax-coloring"&gt;Customizable syntax highlighting&lt;/a&gt; for &lt;tt class="docutils literal"&gt;manage.py&lt;/tt&gt; output,
including highlighting of the development server output.&lt;/li&gt;
&lt;li&gt;A new &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--failfast&lt;/span&gt;&lt;/tt&gt; flag to &lt;tt class="docutils literal"&gt;manage.py test&lt;/tt&gt; that'll stop the running
tests and report immediately after the first test failure.&lt;/li&gt;
&lt;li&gt;And many more.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
</summary></entry><entry><title> I18N/L10N improvements</title><link href="http://djangoadvent.com/1.2/i18n-l10n-improvements/" rel="alternate" /><updated>2010-03-04T00:00:00-11:00</updated><author><name>Jannis Leidel</name><uri>http://jannisleidel.com/</uri></author><id>http://djangoadvent.com/1.2/i18n-l10n-improvements/</id><summary type="html">&lt;p&gt;Django 1.2 comes with a bunch of improvements for the internationalization and
localization machinery, some of which I'd like to introduce here briefly.&lt;/p&gt;
&lt;div class="section" id="formats"&gt;
&lt;h1&gt;Formats&lt;/h1&gt;
&lt;p&gt;Until 1.2, Django had limited support for handling form input and
displaying model data for locales other than US-English. Try to display a
datetime value in the format appropriate to your site's locale (e.g. decimal
and thousand separators) and you'd soon discover you were out of luck.&lt;/p&gt;
&lt;p&gt;Even though Django can handle strings and a few technical messages (e.g.
&lt;tt class="docutils literal"&gt;DATETIME_FORMAT&lt;/tt&gt;), it requires the use of 3rd party tools like the
(fabulous) &lt;a class="reference external" href="http://babel.edgewall.org/"&gt;Babel&lt;/a&gt; to create fully localized sites.&lt;/p&gt;
&lt;p&gt;Thankfully, &lt;a class="reference external" href="http://vaig.be/"&gt;Marc Garcia&lt;/a&gt; worked on that problem during his
&lt;a class="reference external" href="http://vaig.be/2009/04/gsoc-implementation-of-additional-i18n.html"&gt;Summer of Code&lt;/a&gt; in 2009 and laid the foundations for Django's own
formatting engine, which can handle input and output based on the &lt;a class="reference external" href="http://docs.djangoproject.com/en/1.1/topics/i18n/deployment/#how-django-discovers-language-preference"&gt;currently
active language&lt;/a&gt;. Among other features, this includes transparent support for
the admin widgets and the template tags (e.g. &lt;tt class="docutils literal"&gt;{% date %}&lt;/tt&gt;). For example,
with the German locale activated, datetime fields are rendered in the admin
like this:&lt;/p&gt;
&lt;div align="center" class="align-center"&gt;&lt;img alt="datetime field rendered in admin with German locale" class="align-center" src="http://djangoadvent.s3.amazonaws.com/advent/003/admin1.png" /&gt;&lt;/div&gt;
&lt;p&gt;Note how the datetime fields are actually rendered with a format common in
Germany, &lt;tt class="docutils literal"&gt;30.03.2010&lt;/tt&gt; instead of &lt;tt class="docutils literal"&gt;03/30/2010&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;The same applies to numeric fields, e.g. a DecimalField formatted with decimal
and thousands separators:&lt;/p&gt;
&lt;div align="center" class="align-center"&gt;&lt;img alt="datetime field rendered in admin with German locale" class="align-center" src="http://djangoadvent.s3.amazonaws.com/advent/003/admin2.png" /&gt;&lt;/div&gt;
&lt;div class="section" id="custom-formats"&gt;
&lt;h2&gt;Custom formats&lt;/h2&gt;
&lt;p&gt;Django provides format definitions for many locales based on imported data
from the &lt;a class="reference external" href="http://cldr.unicode.org/"&gt;CLDR&lt;/a&gt; (Unicode Common Locale Data Repository), but sometimes you
might want to create your own, because a format file doesn't exist for your
locale, or because you want to overwrite some of the values.&lt;/p&gt;
&lt;p&gt;To use custom formats, specify the path where you'll place format files by
setting &lt;tt class="docutils literal"&gt;FORMAT_MODULE_PATH&lt;/tt&gt; to the Python path where format files will
exists.&lt;/p&gt;
&lt;p&gt;The format files are not placed directly in this directory, but in a
subdirectory with the name of the locale, and they must be named
&lt;tt class="docutils literal"&gt;formats.py&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;To customize the English formats in your project &lt;tt class="docutils literal"&gt;mysite&lt;/tt&gt;, set
&lt;tt class="docutils literal"&gt;FORMAT_MODULE_PATH&lt;/tt&gt; to &lt;tt class="docutils literal"&gt;mysite.formats`&lt;/tt&gt; and create a dictory structure
like this:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
mysite/
    formats/
        __init__.py
        en/
            __init__.py
            formats.py
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="available-formats"&gt;
&lt;h2&gt;Available formats&lt;/h2&gt;
&lt;p&gt;You are probably already familiar with some of the formats because they
were avaibable in earlier Django releases but haven't been hooked up with a
formatting mechanism.&lt;/p&gt;
&lt;p&gt;Valid &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/ref/templates/builtins/#ttag-now"&gt;format strings&lt;/a&gt; in the date and time formats below are of the same format
as the &lt;tt class="docutils literal"&gt;{% now %}&lt;/tt&gt; template tag.&lt;/p&gt;
&lt;div class="section" id="formatting"&gt;
&lt;h3&gt;Formatting&lt;/h3&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;DATE_FORMAT&lt;/tt&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;table class="docutils field-list" frame="void" rules="none"&gt;
&lt;col class="field-name" /&gt;
&lt;col class="field-body" /&gt;
&lt;tbody valign="top"&gt;
&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Default:&lt;/th&gt;&lt;td class="field-body"&gt;&lt;tt class="docutils literal"&gt;'N j, Y'&lt;/tt&gt; (e.g. Feb. 15, 2010)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Default formatting of date fields.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;TIME_FORMAT&lt;/tt&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;table class="docutils field-list" frame="void" rules="none"&gt;
&lt;col class="field-name" /&gt;
&lt;col class="field-body" /&gt;
&lt;tbody valign="top"&gt;
&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Default:&lt;/th&gt;&lt;td class="field-body"&gt;&lt;tt class="docutils literal"&gt;'P'&lt;/tt&gt; (e.g. 4 p.m.)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Default formatting of time fields.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;DATETIME_FORMAT&lt;/tt&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;table class="docutils field-list" frame="void" rules="none"&gt;
&lt;col class="field-name" /&gt;
&lt;col class="field-body" /&gt;
&lt;tbody valign="top"&gt;
&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Default:&lt;/th&gt;&lt;td class="field-body"&gt;&lt;tt class="docutils literal"&gt;'N j, Y, P'&lt;/tt&gt; (e.g. Feb. 15, 2010, 4 p.m.)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Default formatting of datetime fields.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;YEAR_MONTH_FORMAT&lt;/tt&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;table class="docutils field-list" frame="void" rules="none"&gt;
&lt;col class="field-name" /&gt;
&lt;col class="field-body" /&gt;
&lt;tbody valign="top"&gt;
&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Default:&lt;/th&gt;&lt;td class="field-body"&gt;&lt;tt class="docutils literal"&gt;'F Y'&lt;/tt&gt; (e.g. February 2010)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Default formatting of date fields, displaying only year and month.
Used in the admin changelist, et al.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;MONTH_DAY_FORMAT&lt;/tt&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;table class="docutils field-list" frame="void" rules="none"&gt;
&lt;col class="field-name" /&gt;
&lt;col class="field-body" /&gt;
&lt;tbody valign="top"&gt;
&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Default:&lt;/th&gt;&lt;td class="field-body"&gt;&lt;tt class="docutils literal"&gt;'F j'&lt;/tt&gt; (e.g. February 15)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Default formatting of date fields, only displaying month and day.
Used in the admin changelist, et al.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;SHORT_DATE_FORMAT&lt;/tt&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;table class="docutils field-list" frame="void" rules="none"&gt;
&lt;col class="field-name" /&gt;
&lt;col class="field-body" /&gt;
&lt;tbody valign="top"&gt;
&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Default:&lt;/th&gt;&lt;td class="field-body"&gt;&lt;tt class="docutils literal"&gt;'m/d/Y'&lt;/tt&gt; (e.g. 02/15/2010)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A short formatting of date fields.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;SHORT_DATETIME_FORMAT&lt;/tt&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;table class="docutils field-list" frame="void" rules="none"&gt;
&lt;col class="field-name" /&gt;
&lt;col class="field-body" /&gt;
&lt;tbody valign="top"&gt;
&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Default:&lt;/th&gt;&lt;td class="field-body"&gt;&lt;tt class="docutils literal"&gt;'m/d/Y P'&lt;/tt&gt; (e.g. 02/15/2010 4 p.m.)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A short formatting of datetime fields.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;FIRST_DAY_OF_WEEK&lt;/tt&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;table class="docutils field-list" frame="void" rules="none"&gt;
&lt;col class="field-name" /&gt;
&lt;col class="field-body" /&gt;
&lt;tbody valign="top"&gt;
&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Default:&lt;/th&gt;&lt;td class="field-body"&gt;&lt;tt class="docutils literal"&gt;0&lt;/tt&gt; (Sunday)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Number representing the first day of the week. Used in the admin calendar
widget.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;DECIMAL_SEPARATOR&lt;/tt&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;table class="docutils field-list" frame="void" rules="none"&gt;
&lt;col class="field-name" /&gt;
&lt;col class="field-body" /&gt;
&lt;tbody valign="top"&gt;
&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Default:&lt;/th&gt;&lt;td class="field-body"&gt;&lt;tt class="docutils literal"&gt;'.'&lt;/tt&gt; (Dot)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Default decimal separator used when formatting decimal numbers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;THOUSAND_SEPARATOR&lt;/tt&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;table class="docutils field-list" frame="void" rules="none"&gt;
&lt;col class="field-name" /&gt;
&lt;col class="field-body" /&gt;
&lt;tbody valign="top"&gt;
&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Default:&lt;/th&gt;&lt;td class="field-body"&gt;&lt;tt class="docutils literal"&gt;','&lt;/tt&gt; (Comma)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Default thousands separator used when formatting numbers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;NUMBER_GROUPING&lt;/tt&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;table class="docutils field-list" frame="void" rules="none"&gt;
&lt;col class="field-name" /&gt;
&lt;col class="field-body" /&gt;
&lt;tbody valign="top"&gt;
&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Default:&lt;/th&gt;&lt;td class="field-body"&gt;&lt;tt class="docutils literal"&gt;0&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Number of digits grouped together on the integer part of a number. Common
use is to display a thousands separator. If this setting is 0, then, no
grouping will be applied to the number. If this setting is greater than 0
then the setting &lt;tt class="docutils literal"&gt;THOUSAND_SEPARATOR&lt;/tt&gt; will be used as the separator
between those groups.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;If enabled, the English locale has a default of 3.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="handling-input"&gt;
&lt;h3&gt;Handling input&lt;/h3&gt;
&lt;p&gt;There are three separate format strings that will be accepted when inputting
data on a date, time or datetime field. Formats will be tried in order, using
the first valid match. These format strings are specified in &lt;a class="reference external" href="http://docs.python.org/library/datetime.html#strftime-behavior"&gt;Python's datetime&lt;/a&gt;
module syntax, which is different from the one used by Django for formatting
dates to be displayed.&lt;/p&gt;
&lt;p&gt;Use &lt;tt class="docutils literal"&gt;DATE_INPUT_FORMATS&lt;/tt&gt; for date fields, &lt;tt class="docutils literal"&gt;TIME_INPUT_FORMATS&lt;/tt&gt;, for time
fields and &lt;tt class="docutils literal"&gt;DATETIME_INPUT_FORMATS&lt;/tt&gt; for datetime fields.&lt;/p&gt;
&lt;p&gt;Also, have a look at the &lt;a class="reference external" href="http://code.djangoproject.com/browser/django/trunk/django/conf/locale/en/formats.py"&gt;English format file&lt;/a&gt; to see the default values.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="smaller-bugfixes-worth-noting"&gt;
&lt;h1&gt;Smaller bugfixes worth noting&lt;/h1&gt;
&lt;div class="section" id="the-makemessages-command"&gt;
&lt;h2&gt;The &lt;tt class="docutils literal"&gt;makemessages&lt;/tt&gt; command&lt;/h2&gt;
&lt;div class="section" id="ignore"&gt;
&lt;h3&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--ignore&lt;/span&gt;&lt;/tt&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;makemessages&lt;/tt&gt; command now features a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--ignore&lt;/span&gt;&lt;/tt&gt; option. It allows
you to specify a glob pattern of paths it should ignore while traversing the
filesystem in search of marked strings. This is most useful if you have a bunch
of apps in your &amp;quot;project&amp;quot; directory that you don't want to translate in a
monolithic project wide translation catalog but inside their own directories.&lt;/p&gt;
&lt;p&gt;A simple example that will conveniently ignore all directories in the &lt;tt class="docutils literal"&gt;app&lt;/tt&gt;
directory&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;path/to/myproject&lt;span class="o"&gt;]&lt;/span&gt; django-admin.py makemessages -l de --ignore&lt;span class="o"&gt;=&lt;/span&gt;apps/*
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="symlinks"&gt;
&lt;h3&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--symlinks&lt;/span&gt;&lt;/tt&gt;&lt;/h3&gt;
&lt;p&gt;Additionally to the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--ignore&lt;/span&gt;&lt;/tt&gt; option there is now a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--symlinks&lt;/span&gt;&lt;/tt&gt; option,
that will tell &lt;tt class="docutils literal"&gt;makemessages&lt;/tt&gt; to follow symlinks on its quest to find files
containing strings marked for translation &amp;#8212; very useful if you keep your
apps or templates in a central filesystem location.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="plural-forms"&gt;
&lt;h2&gt;Plural forms&lt;/h2&gt;
&lt;p&gt;The plural forms of the default Django translations are now automatically
copied to newly created translation files (&lt;a class="reference external" href="http://code.djangoproject.com/changeset/12445"&gt;changeset 12445&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="order-of-precedence-of-translation-catalogs"&gt;
&lt;h2&gt;Order of precedence of translation catalogs&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="http://code.djangoproject.com/changeset/12447"&gt;r12447&lt;/a&gt; fixed a bug in Django that prevented translation catalogs
located in the &amp;quot;project&amp;quot; directory from sucessfully overriding translations
stored in apps.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="template-filter-in-trans"&gt;
&lt;h2&gt;Template filter in &lt;tt class="docutils literal"&gt;{% trans %}&lt;/tt&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="http://code.djangoproject.com/changeset/12472"&gt;r12472&lt;/a&gt; introduced support for template filters in the &lt;tt class="docutils literal"&gt;trans&lt;/tt&gt;
template tag. The filters will be applied to the result of the translation, e.g.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;load&lt;/span&gt; &lt;span class="nv"&gt;i18n&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;trans&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Welcome!&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Suppose the locale is set to French the template would be rendered as&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;BIENVENUE!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="support-for-idn-internationalized-domain-names"&gt;
&lt;h2&gt;Support for IDN (Internationalized Domain Names)&lt;/h2&gt;
&lt;p&gt;Internationlized Domain Names are domain names that contain characters in a
language-specific script, like Chinese or the Latin-based languages with
diacritics, such as French, that are encoded with Unicode and saved in the
Domain Name System as ASCII strings using the &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Punycode"&gt;Punycode&lt;/a&gt; transcription.&lt;a class="footnote-reference" href="#id2" id="id1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;URLField and EMailField got support for IDNs in &lt;a class="reference external" href="http://code.djangoproject.com/changeset/12474"&gt;r12474&lt;/a&gt; and
&lt;a class="reference external" href="http://code.djangoproject.com/changeset/12620"&gt;r12620&lt;/a&gt; and can now handle domains like &lt;a class="reference external" href="http://新宿駅.jp/"&gt;http://新宿駅.jp&lt;/a&gt; and
&lt;a class="reference external" href="http://räksmörgås.josefsson.org/"&gt;http://räksmörgås.josefsson.org&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="current-locale-in-cache"&gt;
&lt;h2&gt;Current locale in cache&lt;/h2&gt;
&lt;p&gt;When the internationalization mechanism is enabled (if the &lt;tt class="docutils literal"&gt;USE_I18N&lt;/tt&gt; setting
is &lt;tt class="docutils literal"&gt;True&lt;/tt&gt;), Django will append the currently selected language (e.g. &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;en-us&lt;/span&gt;&lt;/tt&gt;)
to the generated cache key, making it easier for multilingual sites to use the
&lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/cache/#the-per-site-cache"&gt;cache middleware&lt;/a&gt; and &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/cache/#the-per-view-cache"&gt;decorator&lt;/a&gt; (&lt;a class="reference external" href="http://code.djangoproject.com/changeset/12546"&gt;r12546&lt;/a&gt; and &lt;a class="reference external" href="http://code.djangoproject.com/changeset/12624"&gt;r12624&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="first-day-of-week"&gt;
&lt;h2&gt;First day of week&lt;/h2&gt;
&lt;p&gt;The admin calendar widget now automatically looks up the first day of the week
in the format modules before rendering. In the &lt;tt class="docutils literal"&gt;formats.py&lt;/tt&gt; simply set
&lt;tt class="docutils literal"&gt;FIRST_DAY_OF_WEEK&lt;/tt&gt; in &lt;tt class="docutils literal"&gt;formats.py&lt;/tt&gt; to a value from 0 to 6, where 0 means
Sunday, 1 means Monday, and so forth.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="internationalization-localization-documentation"&gt;
&lt;h2&gt;Internationalization/localization documentation&lt;/h2&gt;
&lt;p&gt;Luckily, Ramiro Morales refactored the internationalization and localization
documentation (&lt;a class="reference external" href="http://code.djangoproject.com/changeset/12440"&gt;r12440&lt;/a&gt;), so have a look at the &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/i18n/"&gt;new i18n landing page&lt;/a&gt;
to learn more about the intricacies of internationalization.&lt;/p&gt;
&lt;table class="docutils footnote" frame="void" id="id2" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a class="reference external" href="http://en.wikipedia.org/wiki/Internationalized_domain_name"&gt;http://en.wikipedia.org/wiki/Internationalized_domain_name&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
</summary></entry><entry><title>Syndication Gets Classy</title><link href="http://djangoadvent.com/1.2/syndication-gets-classy/" rel="alternate" /><updated>2010-03-03T00:00:00-11:00</updated><author><name>Rob Hudson</name><uri>http://rob.cogit8.org</uri></author><id>http://djangoadvent.com/1.2/syndication-gets-classy/</id><summary type="html">&lt;p&gt;Since its original release&lt;a class="footnote-reference" href="#id3" id="id1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; Django has included support for generating RSS
feeds for content.  RSS, often expanded as &amp;quot;Really Simple Syndication&amp;quot;, is an
XML format used to publish frequently updated content in a standardized format.
Similarly, Django also includes support for generating the Atom Syndication
Format&lt;a class="footnote-reference" href="#id4" id="id2"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;, which is also a standardized format for web feeds that offers a few
&lt;a class="reference external" href="http://en.wikipedia.org/wiki/Atom_(standard)#Atom_compared_to_RSS_2.0"&gt;expanded capabilities&lt;/a&gt; over RSS.&lt;/p&gt;
&lt;table class="docutils footnote" frame="void" id="id3" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;As of &lt;a class="reference external" href="http://code.djangoproject.com/browser/django/trunk/django/core/rss.py?rev=3"&gt;revision 3&lt;/a&gt;, from July 2005, close to 5 years ago.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id4" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Atom feeds were added in &lt;a class="reference external" href="http://code.djangoproject.com/changeset/1194/django/trunk/django"&gt;revision 1194&lt;/a&gt;, from November 2005.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="section" id="prior-to-django-1-2"&gt;
&lt;h1&gt;Prior to Django 1.2&lt;/h1&gt;
&lt;p&gt;While Django's syndication framework offered a very easy way to generate valid
XML, often with just a few lines of Python, it had a number of reported issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Feeds had limited flexibility in the various ways developers wanted to hook
them into &lt;cite&gt;urls.py&lt;/cite&gt;.  For example, if your content is tagged and has HTML views
at urls such as &lt;cite&gt;/tag/django/&lt;/cite&gt;, it was not possible to append an &lt;cite&gt;rss/&lt;/cite&gt;, for
example, to the url to have &lt;cite&gt;/tag/django/rss/&lt;/cite&gt; &amp;#8212; the URL had to adopt the
pattern of &lt;cite&gt;/rss/tag/django/&lt;/cite&gt;.  This is because the URL was constructed in
such a way that it pattern matches a prefix plus the rest of the url:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r&amp;#39;^rss/(?P&amp;lt;url&amp;gt;.*)/$&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;For more complex url patterns, as above, the URL parsing was up to the
developer as the feed class simply split the URL based on the remaining URL
string.  For example, the above URL regular expression would match both
&lt;cite&gt;/rss/tag/django/&lt;/cite&gt; and &lt;cite&gt;/rss/tag/django/other/junk/&lt;/cite&gt;, and it was up to the
developer to catch this and deal with this in the &lt;tt class="docutils literal"&gt;Feed&lt;/tt&gt; class. The problem
here is it leads to URL parsing being in more than one place (i.e.  somewhere
other than the &lt;cite&gt;urls.py&lt;/cite&gt;) and can easily be overlooked.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;There was a little wart where a content item's title and description had to be
defined in a Django template rather than in the feed class, whereas all other
feed attributes could be defined in Python. Often these templates consisted of
&lt;cite&gt;{{ obj.title }}&lt;/cite&gt; and/or &lt;cite&gt;{{ obj.description }}&lt;/cite&gt;, which made no sense to drop
into template rendering.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Plus various other smaller bugs and warts and inconsistencies.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the above issues have been fixed in Django 1.2.  In total, &lt;a class="reference external" href="http://code.djangoproject.com/changeset/12338"&gt;changeset
12338&lt;/a&gt; closed 10 tickets against the syndication framework.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="class-based-views"&gt;
&lt;h1&gt;Class-based Views&lt;/h1&gt;
&lt;p&gt;Besides the above fixes, the change brought with it the introduction of
class-based views.  Previously, while the developer did create a Feed class, it
was called via function-based view (&lt;tt class="docutils literal"&gt;django.contrib.syndication.views.feed&lt;/tt&gt;),
which split the URL to look for the key in the supplied &lt;cite&gt;feed_dict&lt;/cite&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# Django 1.1 and prior&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.conf.urls.defaults&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;myproject.feeds&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LatestEntries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LatestEntriesByCategory&lt;/span&gt;

&lt;span class="n"&gt;feeds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;latest&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;LatestEntries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;categories&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;LatestEntriesByCategory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;patterns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c"&gt;# ...&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r&amp;#39;^feeds/(?P&amp;lt;url&amp;gt;.*)/$&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;django.contrib.syndication.views.feed&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;feed_dict&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;feeds&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As of Django 1.2, the Feed subclass instance is itself a view which results in a
cleaner url pattern and removes the need for a feed dictionary to be defined.
It also removes the need to wildcard match the remaining URL, bringing the URL
pattern matching back into &lt;cite&gt;urls.py&lt;/cite&gt; and out of the Feed class:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.conf.urls.defaults&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;myproject.feeds&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LatestEntries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LatestEntriesByCategory&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;patterns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c"&gt;# ...&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r&amp;#39;^feeds/latest/$&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LatestEntries&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r&amp;#39;^feeds/categories/(?P&amp;lt;category_id&amp;gt;\d+)/$&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LatestEntriesByCategory&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you wanted to flip the URL around, as in the tag example above, you can now
put the named pattern wherever you'd like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;patterns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c"&gt;# ...&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r&amp;#39;^/categories/(?P&amp;lt;category_id&amp;gt;\d+)/feed/$&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LatestEntriesByCategory&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;Feed&lt;/tt&gt; class gets a &lt;cite&gt;category_id&lt;/cite&gt; passed to the &lt;tt class="docutils literal"&gt;get_object&lt;/tt&gt; method of
the class.  The &lt;tt class="docutils literal"&gt;get_object&lt;/tt&gt; method exists for feeds that publish different
data given different URL parameters.  The &lt;tt class="docutils literal"&gt;items&lt;/tt&gt; method then takes the object
returned by &lt;tt class="docutils literal"&gt;get_object&lt;/tt&gt; and returns a list of objects to publish.  In the
example below, this is the last 30 entries in the given category:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.contrib.syndication.views&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FeedDoesNotExist&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.shortcuts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_object_or_404&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LatestEntriesByCategory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Feed&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;get_object_or_404&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;category_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Entry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;-post_date&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)[:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Entries for category &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_absolute_url&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Recent entries in category &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For more details on each method that can be provided, see the &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/ref/contrib/syndication/#feed-class-reference"&gt;feed class
reference&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="using-the-new-syndication-framework"&gt;
&lt;h1&gt;Using the New Syndication Framework&lt;/h1&gt;
&lt;p&gt;The function-based syndication feeds will be around until 1.4, but if you'd like
to take advantage of some of the fixes class-based syndication feeds bring,
upgrading is pretty straight-forward and the &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/releases/1.2/#feed-in-django-contrib-syndication-feeds"&gt;Django 1.2 release notes&lt;/a&gt; are
probably the best source for explaining how to upgrade.&lt;/p&gt;
&lt;p&gt;If you're not already using feeds, the &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/ref/contrib/syndication/"&gt;syndication feed framework docs&lt;/a&gt; offer
all you need to get started, including the aforementioned &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/ref/contrib/syndication/#feed-class-reference"&gt;feed class
reference&lt;/a&gt; for all the methods that are available to override.&lt;/p&gt;
&lt;/div&gt;
</summary></entry><entry><title>Improved Bash Completion</title><link href="http://djangoadvent.com/1.2/improved-bash-completion/" rel="alternate" /><updated>2010-03-02T00:00:00-11:00</updated><author><name>Arthur Koziel</name><uri>http://arthurkoziel.com</uri></author><id>http://djangoadvent.com/1.2/improved-bash-completion/</id><summary type="html">&lt;p&gt;Django 1.2 comes with an improved Bash completion script that enables tab
completion for custom management commands and command options.&lt;/p&gt;
&lt;p&gt;The main problem with the old Bash completion script was that the completions
were hardcoded. This meant that only built-in management
commands (like &lt;tt class="docutils literal"&gt;runserver&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;dumpdata&lt;/tt&gt;) could be tab completed.
Developers, however, commonly extend Django through &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/howto/custom-management-commands/"&gt;custom management
commands&lt;/a&gt;, which made the Bash completion script inconsistent. Tab
completion worked for built-in management commands, but not for
custom ones.&lt;/p&gt;
&lt;p&gt;The Bash completion script in Django 1.2 changes that. Instead of a
hardcoded list of completions, the Bash script was modified to call a Python
function in Django. This function dynamically generates a list of
possible completions based on the actual project settings.
It will take into account the custom management commands from applications
listed in the &lt;tt class="docutils literal"&gt;INSTALLED_APPS&lt;/tt&gt; setting.&lt;/p&gt;
&lt;div class="section" id="installation"&gt;
&lt;h1&gt;Installation&lt;/h1&gt;
&lt;p&gt;To get Django's Bash completion working, you'll first have to install the
&lt;a class="reference external" href="http://bash-completion.alioth.debian.org/"&gt;bash-completion&lt;/a&gt; package. It's a set of functions that enhances Bash's,
otherwise very basic, programmable completion. You can install the package
manually (check the &amp;quot;Installation&amp;quot; section of the projects &lt;a class="reference external" href="http://git.debian.org/?p=bash-completion/bash-completion.git;a=blob;f=README;hb=HEAD#l1"&gt;README file&lt;/a&gt;) or
through a package manager that is available on your operating system.
MacPorts and all major Linux distributions have it available in their
package repositories (it is usually called &amp;quot;bash-completion&amp;quot;).
Ubuntu already ships with the package pre-installed.&lt;/p&gt;
&lt;p&gt;Next up, you'll have to source the &lt;cite&gt;django_bash_completion&lt;/cite&gt; file. It can be
found in the &lt;cite&gt;extras&lt;/cite&gt; directory of an SVN checkout.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;source&lt;/span&gt; /path/to/django_bash_completion
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you installed Django through pip or easy_install, the &lt;cite&gt;extras&lt;/cite&gt; directory
will not be available. In that case, you'll need to &lt;a class="reference external" href="http://code.djangoproject.com/browser/django/trunk/extras/django_bash_completion"&gt;manually download
the file&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The script can be sourced automatically at every login by writing the
command in the &lt;cite&gt;~/.bash_profile&lt;/cite&gt; file.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="usage"&gt;
&lt;h1&gt;Usage&lt;/h1&gt;
&lt;p&gt;Once installed, Bash will generate completions for the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;django-admin.py&lt;/span&gt;&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;django-admin&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;manage.py&lt;/tt&gt; commands. To trigger the completion you'll
have to press the tab key twice after the respective command. For
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;django-admin.py&lt;/span&gt;&lt;/tt&gt;, the output should look like this:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ django-admin.py &amp;lt;TAB&amp;gt;&amp;lt;TAB&amp;gt;
cleanup           inspectdb         sqlall            startapp
compilemessages   loaddata          sqlclear          startproject
createcachetable  makemessages      sqlcustom         syncdb
dbshell           reset             sqlflush          test
diffsettings      runfcgi           sqlindexes        testserver
dumpdata          runserver         sqlinitialdata    validate
flush             shell             sqlreset
help              sql               sqlsequencereset
&lt;/pre&gt;
&lt;p&gt;The same applies to the &lt;tt class="docutils literal"&gt;manage.py&lt;/tt&gt; command of a project.
Note that the &lt;tt class="docutils literal"&gt;manage.py&lt;/tt&gt; file must be executable for this to work. If this
isn't the case, you can run &lt;tt class="docutils literal"&gt;chmod u+x manage.py&lt;/tt&gt; to make it executable.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ ./manage.py &amp;lt;TAB&amp;gt;&amp;lt;TAB&amp;gt;
changepassword    flush             shell             sqlreset
cleanup           help              sql               sqlsequencereset
compilemessages   inspectdb         sqlall            startapp
createcachetable  loaddata          sqlclear          syncdb
createsuperuser   makemessages      sqlcustom         test
dbshell           reset             sqlflush          testserver
diffsettings      runfcgi           sqlindexes        validate
dumpdata          runserver         sqlinitialdata
&lt;/pre&gt;
&lt;p&gt;As you might've noticed, there's a small difference between the generated
completions. The &lt;tt class="docutils literal"&gt;manage.py&lt;/tt&gt; completion will take your project settings
into account. In the above example, the &lt;tt class="docutils literal"&gt;changepassword&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;createsuperuser&lt;/tt&gt;
commands were added because of the installed &lt;tt class="docutils literal"&gt;django.contrib.auth&lt;/tt&gt; application.&lt;/p&gt;
&lt;p&gt;Another example is the &lt;a class="reference external" href="http://pypi.python.org/pypi/django-extensions/"&gt;django-extensions&lt;/a&gt; application, which
adds some useful commands to your Django project. Once you've installed it
and added '&lt;tt class="docutils literal"&gt;django_extensions&lt;/tt&gt;' to your &lt;tt class="docutils literal"&gt;INSTALLED_APPS&lt;/tt&gt; setting,
the Bash completion will include the new commands:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ ./manage.py &amp;lt;TAB&amp;gt;&amp;lt;TAB&amp;gt;
changepassword          help                    shell_plus
clean_pyc               inspectdb               show_urls
cleanup                 loaddata                sql
compile_pyc             mail_debug              sqlall
compilemessages         makemessages            sqlclear
create_app              passwd                  sqlcustom
create_command          print_user_for_session  sqldiff
create_jobs             reset                   sqlflush
createcachetable        reset_db                sqlindexes
createsuperuser         runfcgi                 sqlinitialdata
dbshell                 runjob                  sqlreset
describe_form           runjobs                 sqlsequencereset
diffsettings            runprofileserver        startapp
dumpdata                runscript               sync_media_s3
dumpscript              runserver               syncdata
export_emails           runserver_plus          syncdb
flush                   set_fake_emails         test
generate_secret_key     set_fake_passwords      testserver
graph_models            shell                   validate
&lt;/pre&gt;
&lt;p&gt;Something that wasn't possible with the old completion script is option
completion. You can press the tab key twice after a command to view all of
it's options. For the &lt;tt class="docutils literal"&gt;runserver&lt;/tt&gt; command, the output should look like this:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ ./manage.py runserver &amp;lt;TAB&amp;gt;&amp;lt;TAB&amp;gt;
--adminmedia=  --noreload     --settings=    --verbosity=
--help         --pythonpath=  --traceback
&lt;/pre&gt;
&lt;p&gt;The equal sign after an option name indicates that a value must be specified.&lt;/p&gt;
&lt;p&gt;When using the option completion you'll probably notice that a space
character will be added after each completed word. This can be a little
annoying for options that require a value, as you'll always have to press the
backspace key to set the cursor to the correct position. Sadly, there's
no solution for this. A Bash completion script is initialized
with an option that either outputs a space character after each completed word,
or doesn't. There's no backward compatible solution to change the option after
the script was sourced. Even with the option disabled, you'd have to manually
enter a space character after each completed word.
Bash 4.0 fixed this by introducing a new '&lt;tt class="docutils literal"&gt;compopt&lt;/tt&gt;' builtin that allows
completion functions to modify completion options dynamically. But since
some operating systems ship with an old Bash version (yes, I'm looking
at you Apple) this feature couldn't be used.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="tip-enable-single-tab-completion"&gt;
&lt;h1&gt;Tip: Enable single-tab completion&lt;/h1&gt;
&lt;p&gt;If you have the Readline library installed, you can tell Bash to display the
list of possible completions by pressing the tab key once instead of twice.
This makes the tab completion even more pleasant to use. To change it, write
the following in your &lt;cite&gt;~/.inputrc&lt;/cite&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# enable single tab completion&lt;/span&gt;
&lt;span class="nb"&gt;set &lt;/span&gt;show-all-if-ambiguous on
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="end"&gt;
&lt;h1&gt;End&lt;/h1&gt;
&lt;p&gt;I hope this article has helped you to set up and understand the Bash
completion script for Django 1.2. Hopefully it'll save you some keystrokes in
the future.&lt;/p&gt;
&lt;/div&gt;
</summary></entry><entry><title>Django 1.2 and CSRF</title><link href="http://djangoadvent.com/1.2/django-12-and-csrf/" rel="alternate" /><updated>2010-03-01T00:00:00-11:00</updated><author><name>Andrew Godwin</name><uri>http://www.aeracode.org/</uri></author><id>http://djangoadvent.com/1.2/django-12-and-csrf/</id><summary type="html">&lt;p&gt;CSRF, or Cross-Site Request Forgery, is perhaps one of the most overlooked classes of security vulnerabilities around. SQL injection attacks and cross-site scripting attacks are generally well-understood by any web developer worth their salt, but CSRF attacks often catch them unawares.&lt;/p&gt;
&lt;p&gt;For those unfamiliar with web security in general, CSRF attacks essentially work by using the user's browser, and their pre-existing sessions and cookies, to call other sites with malicious data&lt;a class="footnote-reference" href="#id7" id="id1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;. They're not a server exploit, &lt;em&gt;per se&lt;/em&gt;; they can only affect data on the target site that the user has access to.&lt;/p&gt;
&lt;p&gt;Don't let that fool you, though; there's a large range of nasty things you can do with CSRF, from changing a user's profile to include spam links, to using an administrator's account to delete pages, or slip in backdoors. There have even been remote code execution exploits; it essentially allows the attacker access to anything you have behind authentication or permissions.&lt;/p&gt;
&lt;p&gt;Thankfully, due to the prescience of the Django developers, Django has shipped with a &lt;tt class="docutils literal"&gt;CSRFMiddleware&lt;/tt&gt; for quite a while now, albeit a slightly broken and ill-designed one. To understand more, you first need to understand the basic vector of a CSRF attack.&lt;/p&gt;
&lt;div class="section" id="anatomy-of-a-csrf-attack"&gt;
&lt;h1&gt;Anatomy of a CSRF Attack&lt;/h1&gt;
&lt;p&gt;CSRF works by making the user's browser submit a request (either &lt;tt class="docutils literal"&gt;GET&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;POST&lt;/tt&gt;, depending on the target) to the site being attacked, with the content of the request being chosen by the attacker.&lt;/p&gt;
&lt;p&gt;For example, imagine we have an online bank, with a form that allows us to transfer our money. I want to send some money to Alice (account number 00000001), so I fill out the form, and my browser submits this:&lt;a class="footnote-reference" href="#id8" id="id2"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;pre class="literal-block"&gt;
POST /banking/transfer/ HTTP/1.1
Host: www.andrewsbank.com

amount=100&amp;amp;recipient=00000001
&lt;/pre&gt;
&lt;p&gt;Now, imagine I don't log out of my banking session&lt;a class="footnote-reference" href="#id9" id="id3"&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;, and browse to a malicious site. The site presents me with a button marked &amp;quot;Continue&amp;quot;; however, this is the HTML&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.andrewsbank.com/banking/transfer/&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;POST&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hidden&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;amount&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;100&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hidden&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;recipient&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;00000002&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;submit&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Continue&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, while the button might look innocuous, it's actually sending money to Bob's account (00000002).&lt;/p&gt;
&lt;p&gt;This isn't a particularly sophisticated attack, nor is it a very sophisticated bank (I'd recommend Alice move her money elsewhere). Still, it should hopefully get you thinking about these kinds of attacks, and what they're capable of&lt;a class="footnote-reference" href="#id10" id="id4"&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There's plenty of resources about CSRF attacks on the web if you want to know more; the &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Cross-site_request_forgery"&gt;Wikipedia article&lt;/a&gt; gives a good grounding, and there's a &lt;a class="reference external" href="http://www.codinghorror.com/blog/2008/10/preventing-csrf-and-xsrf-attacks.html"&gt;good article&lt;/a&gt; by Jeff Atwood.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="protecting-against-csrf"&gt;
&lt;h1&gt;Protecting against CSRF&lt;/h1&gt;
&lt;p&gt;So, how does one stop CSRF attacks? The underlying method is to make sure every request originated from a real use of your site, and isn't spoofed.&lt;/p&gt;
&lt;p&gt;The general method is to generate a token for every form (a &lt;em&gt;nonce&lt;/em&gt; in security parlance), tied to the user's session, and to check the user's &lt;tt class="docutils literal"&gt;REFERER&lt;/tt&gt; header. Tying it to the session is crucial; without it, the attacking site could simply perform a request to your site itself and obtain a valid token.&lt;/p&gt;
&lt;p&gt;However, if you do check the session, and make sure you issued the token relatively recently, you can be reasonably sure it's a valid request. There's never really any certainty in computer security, and new attacks are being discovered all the time&lt;a class="footnote-reference" href="#id11" id="id5"&gt;&lt;sup&gt;5&lt;/sup&gt;&lt;/a&gt;, but you're still a lot better off.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="django-and-csrf"&gt;
&lt;h1&gt;Django and CSRF&lt;/h1&gt;
&lt;p&gt;Now, back to the aforementioned &lt;tt class="docutils literal"&gt;CSRFMiddleware&lt;/tt&gt;. The version of this shipped with Django 1.1 was lacking, at best; it took the output of your site, ran a regular expression over it that looked for &lt;tt class="docutils literal"&gt;&amp;lt;form&amp;gt;&lt;/tt&gt; elements, and then added an &lt;tt class="docutils literal"&gt;&amp;lt;input&amp;gt;&lt;/tt&gt; element containing the CSRF token, which incoming &lt;tt class="docutils literal"&gt;POST&lt;/tt&gt; requests were checked for.&lt;/p&gt;
&lt;p&gt;As well as the obvious issue of it just running regular expressions over and inserting content into your response stream, it also added tokens to every POSTable form on the page - including ones which submitted to a third-party site, sending a valid CSRF token along with the other data. Armed with that token, the third-party site could then have used it to mount a CSRF attack on that user.&lt;/p&gt;
&lt;p&gt;There were also other problems with the old CSRF protection; for example, it required &lt;tt class="docutils literal"&gt;SessionMiddleware&lt;/tt&gt; to be enabled, and it wasn't really possible to enable it only for one app, as middleware is global.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="what-s-changed"&gt;
&lt;h1&gt;What's Changed?&lt;/h1&gt;
&lt;p&gt;In Django 1.2, the regex-happy &lt;tt class="docutils literal"&gt;CsrfMiddleware&lt;/tt&gt; has gone, and a new one has appeared in its place, sporting more features along with a distinct lack of regular expressions.&lt;/p&gt;
&lt;p&gt;The new CSRF protection also requires that you insert the &lt;tt class="docutils literal"&gt;{% csrf_token %}&lt;/tt&gt; tag inside any &lt;tt class="docutils literal"&gt;&amp;lt;form&amp;gt;&lt;/tt&gt; elements you want to have CSRF protection, rather than just adding it to all forms. While this means you have to remember to add the tag to all forms which submit to CSRF-protected views, it also means that you won't accidentally send valid tokens off to third-party sites, like before.&lt;/p&gt;
&lt;p&gt;In addition, the new protection also doesn't need to be enabled globally to be effective; there's a new &lt;tt class="docutils literal"&gt;django.views.decorators.csrf.csrf_protect&lt;/tt&gt; decorator that you can use to enable CSRF on a per-view basis, and which all of the core Django apps now use, meaning your admin pages are secure even if you've turned off the middleware.&lt;/p&gt;
&lt;p&gt;CSRF protection has also been promoted from being a contrib app to being part of Django core; this is because we believe that, much like auto-escaping, CSRF is a vital part of what a web framework should provide; it's very easy to get wrong if you implement it yourself.&lt;/p&gt;
&lt;p&gt;Finally, the new protection uses its own cookie directly, rather than relying on Django's built-in sessions, so if you're using a different way of storing user state, such as signed cookies, it will still work.&lt;/p&gt;
&lt;p&gt;(If you were an avid user of the old &lt;tt class="docutils literal"&gt;CsrfMiddleware&lt;/tt&gt;, don't worry; it's been preserved as &lt;tt class="docutils literal"&gt;django.middleware.csrf.CsrfResponseMiddleware&lt;/tt&gt;, and will stay around until Django 1.4.)&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="gotchas"&gt;
&lt;h1&gt;Gotchas&lt;/h1&gt;
&lt;p&gt;Any reasonably magic solution has 'gotchas', and even the new CSRF protection is no exception.&lt;/p&gt;
&lt;p&gt;Firstly, due to cookie subdomain rules, the CSRF protection does not protect you against any malicious subdomains on the same domain as you; they can easily retrieve the cookie's value, and use it to send requests. The obvious solution to this is to make sure your subdomains are all trusted, although that can be more difficult than it initially sounds&lt;a class="footnote-reference" href="#id12" id="id6"&gt;&lt;sup&gt;6&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Secondly, this protection won't work on outgoing AJAX requests, or custom content renderers. Incoming AJAX requests are not an issue; browsers have a same-origin policy, and so the CSRF protection won't try to check them (they can be identified by their headers).&lt;/p&gt;
&lt;p&gt;However, if you're sending HTML out manually as strings, or via a different template library, you'll need to make sure you manually embed the token yourself - you can use &lt;tt class="docutils literal"&gt;django.middleware.csrf.get_token()&lt;/tt&gt; to get a valid token to send.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;CSRF is a hard problem, and one that isn't fully solved yet in Django (and may well never be). However, much like auto-escaping, the aim is to give you a solid, reasonably secure base to work from, and on this front, the new CSRF protection is a good move forward - it's now up to you to make sure you use it!&lt;/p&gt;
&lt;table class="docutils footnote" frame="void" id="id7" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;As Wikipedia puts it, it &amp;quot;exploits the site's trust in the browser&amp;quot;. By contrast, XSS explots the browser's trust in the site.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id8" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;This isn't valid HTTP, so please don't send angry letters. I'm trying to illustrate a point here.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id9" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id3"&gt;[3]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;A lot of people would just close the tab, or browse to another page, or hit back. If there's one thing that web users are good at, it's doing things in a completely illogical manner.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id10" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id4"&gt;[4]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;CSRF vulnerabilites have &lt;em&gt;actually&lt;/em&gt; been discovered in online banking interfaces; see Jeff Atwood's article, linked below.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id11" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id5"&gt;[5]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Such as click-through attacks, where your site is loaded in a mostly-invisible &lt;tt class="docutils literal"&gt;&amp;lt;iframe&amp;gt;&lt;/tt&gt;, and a crucial button (such as 'delete') is then placed so you click on it, thinking it's part of the attacking site.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id12" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id6"&gt;[6]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;If any subdomain allows running arbitary external code in its context, you've got a security hole, for example. This may not seem bad at first, but lots of sites simply embed third-party JavaScript snippets, like Google Analytics, without a second thought.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</summary></entry><entry><title>Django Pony: A Retrospective</title><link href="http://djangoadvent.com/1.2/django-pony-retrospective/" rel="alternate" /><updated>2010-02-26T00:00:00-11:00</updated><author><name>A. Drew Downing</name><uri>http://twitter.com/adrewdowning</uri></author><id>http://djangoadvent.com/1.2/django-pony-retrospective/</id><summary type="html">&lt;p&gt;In recent years, we have seen the meteoric rise to fame of Django's mascot, the
much-loved Django Pony; with universal acclaim, she has been a guiding symbol,
uniting Django developers worldwide.&lt;/p&gt;
&lt;p&gt;Yet the turbulent history of this well-known figure is relatively unknown; her
past is shrouded in mystery so deep that even our highly underpaid researchers
had trouble unmasking it, even with the help of our anonymous source.&lt;a class="footnote-reference" href="#id11" id="id1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Django Pony's formative years are the most mysterious of all; there are no
birth records for any member of &lt;em&gt;Equus Volatilis&lt;/em&gt; from that period; given the
rare breed, this is very odd, even taking the species' magical powers into
consideration.&lt;/p&gt;
&lt;p&gt;Indeed, there have been rumours that Django Pony is not all she appears to be;
in a leaked document from late 2008, there are claims that Django Pony is in
fact a mechanically-operated exoskeletal animatronic body - while this may seem
implausible, after extensive research&lt;a class="footnote-reference" href="#id12" id="id2"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; we've determined it is indeed
possible, provided you have enough funding, and at least two (but possibly
three) mad scientists.&lt;/p&gt;
&lt;p&gt;(Our attempts to replicate the effect with a cat, cardboard tubes, and fake fur
were unsuccessful, although the research department believes this is due to an
insufficient number of captions on the cat&lt;a class="footnote-reference" href="#id13" id="id3"&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;To try and verify this rumour, we sent one of our best researchers undercover
to try and obtain a DNA sample for analysis, during one of Django Pony's few
public appearances. Unfortunately, he returned with only a autographed
hoofprint and a moderately brighter outlook on life; we suspect that Django
Pony must be equipped with a lower-power version of Steve Jobs' Reality
Distortion Field.&lt;a class="footnote-reference" href="#id14" id="id4"&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;However, while her early years are still mostly unknown, a great deal more is
known about her more recent activities. In 2007, Django Pony moved to
California in search of a new life. With an image that appealed to the younger
generation, she was quickly doing photoshoots for small businesses, and was the
logo for My Little Pony's short-lived &amp;quot;My Little Glue Factory&amp;quot; set.&lt;/p&gt;
&lt;p&gt;Unsatisfied with small-time adverts and minor branding, she was looking for a
big break - a major branding opportunity. Luckily, news came through that the
Django community (well known as one of the world's finest social groups) was
holding a conference nearby, and that local speaker Cal Henderson was to give
one of the keynotes.&lt;/p&gt;
&lt;p&gt;Cal is, of course, a master of deception and subliminal messaging. In exchange
for a bribe&lt;a class="footnote-reference" href="#id15" id="id5"&gt;&lt;sup&gt;5&lt;/sup&gt;&lt;/a&gt;, he wove the idea of the Django Pony into his presentation,
leaving subtle&lt;a class="footnote-reference" href="#id16" id="id6"&gt;&lt;sup&gt;6&lt;/sup&gt;&lt;/a&gt; hints everywhere. One man - a certain Bryan Veloso - was
particularly affected by Cal's psychological onslought, and succumbed,
spearheading the overwhelmingly successful appointment of Django Pony as
community mascot.&lt;/p&gt;
&lt;p&gt;Drunk with her newfound fame, and pleased at how quickly and easily the
community had succumbed, Django Pony toured the country, meeting Django
developers everywhere, helping with bug reports and code reviews; the effect
was overwhelmingly beneficial, and as the new year came around, a revitalized
and energetic Django community headed for PyCon, led by their new figurehead.&lt;/p&gt;
&lt;p&gt;Determined to make her first major public appearance holding the new position
of Django mascot, she arrived in Chicago buoyed by optimism. However, things
quickly turned ugly; a gang of rogue Django developers known only as 'Pinax'
decided to kidnap Django Pony for their own nefarious purposes. Thankfully,
Django Pony managed to escape with only a &lt;a class="reference external" href="http://www.flickr.com/photos/bastispicks/3400633546/"&gt;minimum of casualties&lt;/a&gt;.&lt;a class="footnote-reference" href="#id17" id="id7"&gt;&lt;sup&gt;7&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Shocked by her hostage experience, Django Pony turned to both &lt;a class="reference external" href="http://picasaweb.google.com/lh/photo/UT35MQmKCiy9QCnnhsbgIg?feat=directlink"&gt;alcohol&lt;/a&gt;
and even &lt;a class="reference external" href="http://ponysex.us/"&gt;one night stands&lt;/a&gt; to try and forget the
experience, ending up wandering the streets of Chicago in a drug-induced haze.
Luckily, she was found by a group of core Python contributors, out hunting the
GIL&lt;a class="footnote-reference" href="#id18" id="id8"&gt;&lt;sup&gt;8&lt;/sup&gt;&lt;/a&gt;, and taken back to the hotel.&lt;/p&gt;
&lt;p&gt;Both hungover and humbled, Django Pony realised the error of her ways, and
decided to try and help the community, ushering attendees into Django talks,
erasing mentions of Zope and Pylons from the programme, and even making up with
a (now reassembled) &lt;a class="reference external" href="http://www.flickr.com/photos/bastispicks/3396812647/"&gt;James Tauber&lt;/a&gt;, as well as many other
Django developers.&lt;/p&gt;
&lt;p&gt;She went on to make appearances at EuroDjangoCon 2009 and then DjangoCon 2009,
clearly a reformed character; she was crucial in finally getting Django 1.1 out
the door, even flying down to Australia with a copy of the Trac database,
allowing Russ to finally download more than five tickets an hour over his
cutting-edge Australian internet.&lt;/p&gt;
&lt;p&gt;However, there are still many unanswered questions about the Django Pony. How
did she get her name? How do those wings fold away when she's not flying? More
importantly, is there any substance to the rumour that she stole the magic
removed from Django itself four years ago?&lt;a class="footnote-reference" href="#id19" id="id9"&gt;&lt;sup&gt;9&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Even with these mysteries, though, we can still conclude that Django Pony has
definitely been of benefit to the Django community; in a year where so many
other technologies were competing, Django has steamed ahead, with new features,
new committers, and new releases, and if Django Pony has anything to do with
it, this coming year will be even better.&lt;a class="footnote-reference" href="#id20" id="id10"&gt;&lt;sup&gt;10&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;table class="docutils footnote" frame="void" id="id11" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;He went only by the codename 'Jake Obyan'.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id12" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;We checked it using The Google, and it got lots of hits.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id13" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id3"&gt;[3]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Of course, it's a well-known fact that captions slow down cats; they're often employed so a picture can be taken without motion blur.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id14" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id4"&gt;[4]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Fortunately, Django Pony's version seems to lack the original's ability to cause mass hysteria and inflate stock prices.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id15" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id5"&gt;[5]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;The bribe was later confirmed to be approximately three hundred t-shirts.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id16" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id6"&gt;[6]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;We suspect &lt;a class="reference external" href="http://www.flickr.com/photos/yashh/2835538558/"&gt;this image&lt;/a&gt; may contain some kind of hidden message, although our analysts are still working on it.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id17" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id7"&gt;[7]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Pinax team members are extremely modular and reuseable; the team was quickly reassembled, although they never did find James' spleen.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id18" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id8"&gt;[8]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Guido van Rossum, supreme overlord of Python, has offered a significant prize for anyone who can kill the GIL; nobody has yet succeeded.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id19" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id9"&gt;[9]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Simon claims it was out of his sight for only a few minutes; whoever took it was clearly either a professional, or distracted him with a minature zeppelin.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id20" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id10"&gt;[10]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Unless Django Pony's &lt;a class="reference external" href="http://www.break.com/pictures/going-up-on-the-fridge!1650666.html"&gt;evil twin&lt;/a&gt; has anything to do with it; she's on a personal vendetta against multi-db support. Alex Gaynor will soon be taken into protective custody.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</summary></entry><entry><title>Scaling Django</title><link href="http://djangoadvent.com/1.2/scaling-django/" rel="alternate" /><updated>2010-02-25T00:00:00-11:00</updated><author><name>Mike Malone</name><uri>http://immike.net</uri></author><id>http://djangoadvent.com/1.2/scaling-django/</id><summary type="html">&lt;p&gt;I started using Django 0.96 about two years ago while working on the social messaging website &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Pownce"&gt;Pownce&lt;/a&gt;. At that time, Pownce was one of the largest Django sites on the net. A lot of work had gone into making Django a robust platform for general web development, but the Django community hadn't put much effort into making the framework operate at &amp;quot;web scale.&amp;quot; In other words, there wasn't much interest in providing facilities for running a distributed, high availability system like those found at Facebook, Google, and Amazon &amp;#8212; And it showed.&lt;/p&gt;
&lt;p&gt;Since then, a lot of work has gone into balancing the needs of the thousands of small-scale Django sites with the demands of the relatively few large Django installs. There's still a lot of custom code required to use Django at scale, but that's to be expected &amp;#8212; scaling is very application specific. The best we can hope for is a framework that provides the basic tools we need, then gets out of our way. And, for the most part, Django does just that.&lt;/p&gt;
&lt;div class="section" id="scalability"&gt;
&lt;h1&gt;Scalability&lt;/h1&gt;
&lt;p&gt;Scalability is a property that indicates a system's ability to accommodate increased usage or increased data volume. There are lots of things that will need to scale as your site grows: your team, your business model, your issue tracking system, etc. But I'm going to focus on the technical bits. A scalable Django application should be able to handle more traffic without requiring changes to the code base or architecture.&lt;/p&gt;
&lt;p&gt;Turns out, making a scalable Django app isn't all that different from making a scalable app using any other language or framework. That said, I will try to tie things back to Django where appropriate.&lt;/p&gt;
&lt;div class="attention"&gt;
&lt;p class="first admonition-title"&gt;Attention!&lt;/p&gt;
&lt;p class="last"&gt;Caution: scalability and performance are often confused. They are two very different things. If my website can respond to your request in 10ms it's fast. If it can respond to your request and millions of others simultaneously without failing, it's scalable. The two concepts are related, but not interchangeable.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="gathering-stats"&gt;
&lt;h1&gt;Gathering Stats&lt;/h1&gt;
&lt;p&gt;Let's pretend we just launched a new Django powered website. As data starts pouring into our system we start finding pages that used to load instantly now take five or ten seconds to materialize. Don't panic. The first step at this point is to gather information. Unless we're running some terribly inefficient algorithm, chances are the database is our bottleneck (this will be a common theme as a site grows, by the way). So we need to figure out what queries are running, and hope we come across some low-hanging fruit.&lt;/p&gt;
&lt;p&gt;Screwing around in a production environment is generally a bad idea, so hopefully there's a staging or development environment that we can work with. Using a staging environment is an accepted best practice, but it's also important that this environment has a dataset that's similar in size and composition to production. Joining two tables with a few thousand rows is practically free. Try the same join on two tables with millions of rows each and you'll get quite different results. A replica of the production database should do just fine.&lt;/p&gt;
&lt;p&gt;The Django ORM is awesome. It makes it really easy to interact with a relational database and generate complex SQL in a clean, pythonic way. Unfortunately, it also makes it easy to generate inefficient queries that join across dozens of tables, or run thousands of queries for a single request. As our site grows, we'll need lots of insight into how our database is being queried so we can add indexes and tweak our configuration for optimal performance. But the ORM abstraction also makes the inner workings of the underlying database fairly opaque. Thankfully, there are a couple of tools and tricks that can help out.&lt;/p&gt;
&lt;p&gt;The &lt;a class="reference external" href="http://github.com/robhudson/django-debug-toolbar"&gt;Django Debug Toolbar&lt;/a&gt; provides a ton of useful information. It captures every query executed during a request, and injects a debug panel into your output HTML with detailed statistics including query execution time, total request time, and logging output.&lt;/p&gt;
&lt;p&gt;If you don't want to install the debug toolbar, you can roll your own tools by poking around at the &lt;tt class="docutils literal"&gt;django.db.connection&lt;/tt&gt; object (or &lt;tt class="docutils literal"&gt;django.db.connections dictionary&lt;/tt&gt;, if you're using multi-db). When debug mode is turned on, Django records query execution times in the &lt;cite&gt;queries&lt;/cite&gt; attribute of the connection object:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;foo.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Bar&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Bar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Bar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Bar&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queries&lt;/span&gt;
&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;time&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;0.071&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;sql&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;u&amp;#39;SELECT &amp;quot;foo_bar&amp;quot;.&amp;quot;id&amp;quot;, &amp;quot;foo_bar&amp;quot;.&amp;quot;name&amp;quot;, &amp;quot;foo_bar&amp;quot;.&amp;quot;age&amp;quot;, &amp;quot;foo_bar&amp;quot;.&amp;quot;created&amp;quot; FROM &amp;quot;foo_bar&amp;quot; WHERE &amp;quot;foo_bar&amp;quot;.&amp;quot;id&amp;quot; = 1 &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you're just wondering what SQL a particular operation generates, the ORM can tell you that too (note that this functionality has changed in Django 1.2):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;foo.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Bar&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Mike&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s"&gt;&amp;#39;SELECT &amp;quot;foo_bar&amp;quot;.&amp;quot;id&amp;quot;, &amp;quot;foo_bar&amp;quot;.&amp;quot;name&amp;quot;, &amp;quot;foo_bar&amp;quot;.&amp;quot;age&amp;quot;, &amp;quot;foo_bar&amp;quot;.&amp;quot;created&amp;quot; FROM &amp;quot;foo_bar&amp;quot; WHERE &amp;quot;foo_bar&amp;quot;.&amp;quot;name&amp;quot; = Mike &amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can take this output and gain further insight using the explain statement on your database's shell (available on &lt;a class="reference external" href="http://dev.mysql.com/doc/refman/5.1/en/using-explain.html"&gt;MySQL&lt;/a&gt; and &lt;a class="reference external" href="http://www.postgresql.org/docs/8.1/static/sql-explain.html"&gt;PostgreSQL&lt;/a&gt;, at least). This should give you enough information to speed things up by adding indexes or adjusting the query.&lt;/p&gt;
&lt;p&gt;Aside from simply paying attention to queries during development, you should use a monitoring package like &lt;a class="reference external" href="http://munin.projects.linpro.no/"&gt;Munin&lt;/a&gt; or &lt;a class="reference external" href="http://ganglia.sourceforge.net/"&gt;Ganglia&lt;/a&gt; to track database operations, web requests, and other interesting technical and business metrics. If you see an increase in database queries you should be able to correlate it with a business metric like posts per second. If you can't, you may have a bug. Dig deeper.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="caching"&gt;
&lt;h1&gt;Caching&lt;/h1&gt;
&lt;p&gt;So we've removed some joins, added some indexes, and done a bit of denormalization. But there are still a couple of big hairy queries that take too long and simply can't be eliminated. One of the easiest ways to increase throughput for this sort of expensive operation is to do them less often and cache the result. Don't use cache as a crutch &amp;#8212; an app shouldn't completely fail when its cache is invalidated &amp;#8212; but intelligent caching can dramatically improve the performance and scalability of a web app.&lt;/p&gt;
&lt;p&gt;Django's &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/cache/"&gt;cache abstraction&lt;/a&gt; can be configured to use a couple of different &amp;quot;backends.&amp;quot; The only option that's appropriate for production use is &lt;a class="reference external" href="http://memcached.org/"&gt;memcached&lt;/a&gt;. There are also a number of high-level cache abstractions like the per-site cache and per-view cache. Unfortunately, these are pretty useless if you're serving up highly personalized pages. Rather than caching rendered HTML, I typically cache raw data using the low-level cache API.&lt;/p&gt;
&lt;p&gt;The basic cache pattern is pretty simple, here's an example from the Pownce code base:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.core.cache&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_social_network_profiles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;cache_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;networks_for_&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
        &lt;span class="n"&gt;profiles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cache_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;profiles&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;profiles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;social_network_profiles&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cache_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;profiles&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;profiles&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But caching is the easy part. As Phil Karlton famously said, &amp;quot;there are only two hard problems in Computer Science: cache invalidation, and naming things.&amp;quot; So how do we invalidate the cache and keep from serving up stale information when our User record is updated? Fortunately, &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/signals/"&gt;Django signals&lt;/a&gt; make this easy too:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.core.cache&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.db.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;signals&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;nuke_social_network_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;cache_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;networks_for_&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
    &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cache_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;signals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post_save&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nuke_social_network_cache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;SocialNetworkProfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;signals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post_delete&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nuke_social_network_cache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;SocialNetworkProfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Keeping cached counters is another great way to reduce database load. Count how many words are in this sentence. Unless you're rain man, you had to look at each word to come up with an answer, right? The same is true when you ask a database to count how many messages a user sent yesterday. The database may get some help from indexes, but it basically has to perform the query to get the result. And that's not cheap.&lt;/p&gt;
&lt;p&gt;Luckily, as of Django 1.1 memcached's atomic increment and decrement operations have been exposed by the Django cache API. Again, the pattern is pretty simple:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;incr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cache_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c"&gt;# nonexistent key raises ValueError&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count_the_hard_way&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cache_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And again, signal handlers are an excellent way to keep counters up to date without peppering your code with increment and decrement operations.&lt;/p&gt;
&lt;p&gt;Speaking of counts, Django's built-in &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/pagination/"&gt;pagination functionality&lt;/a&gt; is often the culprit of extraneous count operations. If you're using the Django object paginator you may want to toy with one of the &lt;a class="reference external" href="http://www.djangozen.com/blog/faster-or-lazier-pagination"&gt;several&lt;/a&gt; &lt;a class="reference external" href="http://code.google.com/p/django-pagination/"&gt;countless&lt;/a&gt; &lt;a class="reference external" href="http://gist.github.com/213702"&gt;pagination&lt;/a&gt; implementations floating around the web.&lt;/p&gt;
&lt;p&gt;There are a couple of features that the Django cache abstraction is missing. There's no way to cache an object without an expiration time (e.g., cache an object until it's explicitly invalidated), which is useful for objects that are fetched frequently, but rarely change, like user profiles. And the cache compression functionality that's part of the Python memcache library isn't exposed. If you're running out of memory, but have CPU cycles to spare, compressing cached objects can be a big win. Luckily, the Django cache infrastructure allows you to specify your own custom cache backend. So it's pretty easy to write a backend that exposes both of these features (full version &lt;a class="reference external" href="http://gist.github.com/299905"&gt;on GitHub&lt;/a&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.core.cache.backends&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;memcached&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.utils.encoding&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;smart_unicode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;smart_str&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CacheClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memcached&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CacheClass&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_compress_len&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;150000&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;unicode&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default_timeout&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_cache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;smart_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_compress_len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To enable our custom backend, simply use the full module and class name for the CACHE_BACKEND setting in settings.py:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
CACHE_BACKEND = 'package.mymemcached://127.0.0.1:11211/'
&lt;/pre&gt;
&lt;p&gt;Finally, If you find yourself caching lots of individual model objects, you may want to handle cache fetches and invalidation transparently to reduce code duplication and keep the Django ORM interface. A custom QuerySet with an overridden get method can serve lookups by primary key from cache, and invalidation can be handled via signals. This is a technique we used at Pownce, and it worked wonderfully. If this sounds useful, feel free to grab the &lt;a class="reference external" href="http://github.com/mmalone/django-caching"&gt;automatic model object caching&lt;/a&gt; code I've posted on GitHub.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="load-balancing"&gt;
&lt;h1&gt;Load Balancing&lt;/h1&gt;
&lt;p&gt;Once we've got our queries optimized and cache infrastructure in place our next bottleneck is probably going to be our app server. That is, the actual machine running our Django app. At some point it will simply not have the capacity to serve additional requests, it will start backlogging connections, and eventually become unresponsive.&lt;/p&gt;
&lt;p&gt;Luckily, Django uses a shared-nothing architecture out of the box. As long as you're using the &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/http/sessions/#using-cached-sessions"&gt;cache&lt;/a&gt; or &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/http/sessions/#using-database-backed-sessions"&gt;database&lt;/a&gt; session backends, there is no single point of contention at the app server level. Responsibility for maintaining a consistent application state is pushed down the stack (to the database) leaving the application tier free to scale horizontally. So, when one app server reaches capacity, simply add another.&lt;/p&gt;
&lt;p&gt;Of course it's slightly more complicated than that. In order to spread load between multiple application servers we need to use a load balancer. There are several varieties of load balancers available. They can be hardware or software, and can operate at different levels of the &lt;a class="reference external" href="http://en.wikipedia.org/wiki/OSI_model"&gt;OSI stack&lt;/a&gt; (usually layer 4 or layer 7).&lt;/p&gt;
&lt;p&gt;Hardware balancers are highly efficient, highly reliable, and extremely expensive. A common setup for a large operation is to use redundant layer 4 hardware balancers (e.g., &lt;a class="reference external" href="http://www.f5.com/products/big-ip/"&gt;Big-IPs&lt;/a&gt;) in front of a pool of layer 7 software balancers. But those two hardware balancers, with a maintenance contract, can cost in the neighborhood of $100,000. If you don't have that kind of money, fear not. A good open source software balancer like &lt;a class="reference external" href="http://www.danga.com/perlbal/"&gt;Perlbal&lt;/a&gt;, &lt;a class="reference external" href="http://nginx.org/"&gt;nginx&lt;/a&gt;, or &lt;a class="reference external" href="http://haproxy.1wt.eu/"&gt;HAProxy&lt;/a&gt; will get the job done, and cost no more than the hardware they run on (which, by the way, doesn't have to be that powerful &amp;#8212; Pownce had a single Perlbal balancer that ran with a pretty steady 0.00 load).&lt;/p&gt;
&lt;p&gt;But the best way to reduce load on your app servers is much simpler &amp;#8212; don't use them to do hard stuff.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="queuing"&gt;
&lt;h1&gt;Queuing&lt;/h1&gt;
&lt;p&gt;A queue is simply a bucket that holds messages until they are removed for processing by a client. Any expensive operation that an app performs should be queued and completed asynchronously. A simple example is note distribution on Pownce: like Twitter, Pownce had to distribute any note you sent to all of your followers. Notes were associated with recipients using a simple join table. So note distribution required an insert per follower. Since some users had thousands, or tens of thousands of followers, this operation could be quite expensive.&lt;/p&gt;
&lt;p&gt;So, rather than distributing notes immediately, we'd stick them in a queue and send them to your followers out of band. Since you would notice if the message you just sent didn't show up in your own inbox, we'd do that insert synchronously. The rest of your followers would see your note as soon as a consumer got around to distributing it &amp;#8212; typically this would happen in a few seconds to a minute.&lt;/p&gt;
&lt;p&gt;Like load balancers, there are tons of open source queue packages. Some of my favorites are &lt;a class="reference external" href="http://www.danga.com/gearman/"&gt;Gearman&lt;/a&gt;, &lt;a class="reference external" href="http://www.rabbitmq.com/"&gt;RabbitMQ&lt;/a&gt;, &lt;a class="reference external" href="http://activemq.apache.org/"&gt;ActiveMQ&lt;/a&gt;, and &lt;a class="reference external" href="http://www.zeromq.org/"&gt;ZeroMQ&lt;/a&gt;. These tools provide lots of fancy features: brokers, exchanges, routing keys, bindings, etc. (You can &lt;a class="reference external" href="http://blogs.digitar.com/jjww/2009/01/rabbits-and-warrens/"&gt;read more here&lt;/a&gt;.) But don't let that stuff distract from the fact that this is a pretty simple concept. It's a to-do list, nothing more.&lt;/p&gt;
&lt;p&gt;Assuming you want to use the ORM, the clients that consume queue jobs will likely be standalone Django scripts. These can be rather confusing to write if you're just getting started with the framework. Luckily, &lt;a class="reference external" href="http://www.b-list.org"&gt;James Bennett&lt;/a&gt; has an &lt;a class="reference external" href="http://www.b-list.org/weblog/2007/sep/22/standalone-django-scripts/"&gt;excellent article on writing standalone scripts&lt;/a&gt; that should demystify the process. The basic pattern is pretty straightforward though. Just start your scripts thusly:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.core.management&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;setup_environ&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;mysite&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;span class="n"&gt;setup_environ&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There are also a number of interesting projects that aim to simplify queuing and provide a more Pythonic interface that integrates nicely with Django. Honestly, I haven't used any of these myself, but &lt;a class="reference external" href="http://github.com/ask/carrot"&gt;Carrot&lt;/a&gt;, &lt;a class="reference external" href="http://celeryproject.org/"&gt;Celery&lt;/a&gt;, and &lt;a class="reference external" href="http://github.com/nathanborror/flopsy"&gt;Flopsy&lt;/a&gt; all look useful.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-database"&gt;
&lt;h1&gt;The Database&lt;/h1&gt;
&lt;p&gt;With a couple of app servers, liberal use of caching, and an asynchronous queue mechanism for expensive operations we should be able to grow our site to a respectable size. However, up until this point we've been ignoring the one component of the typical Django app's architecture that is truly difficult to scale: the database. Like the app tier, in order to scale our data tier we'll need to add more machines. But in this case it turns out to be quite a bit trickier.&lt;/p&gt;
&lt;p&gt;The simplest way to add capacity and fault tolerance to the data tier is to use replication. And the simplest form of replication is master-slave replication. With MySQL master-slave replication, for example, every data manipulation or data definition query is executed on the master then sent over the network to be executed on the slave, or &amp;quot;replica.&amp;quot; Thus, write operations are performed by both machines. Since the replica maintains an up-to-date copy of the master's data set, read operations can be distributed between the two nodes. And since 80 to 90% of the database operations executed by a typical web app are reads, adding read capacity via replication can get you a long way. For what it's worth, Pownce never grew past this form of replication.&lt;/p&gt;
&lt;div class="tip"&gt;
&lt;p class="first admonition-title"&gt;Tip&lt;/p&gt;
&lt;p class="last"&gt;Tip: It's important to ensure that data is never written to your slave database. One simple way to achieve this is to configure Django to use an account with read-only access to your slave database.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Prior to Django 1.2 you had to &lt;a class="reference external" href="http://www.eflorenzano.com/blog/post/easy-multi-database-support-django/"&gt;jump through hoops&lt;/a&gt; to work with multiple databases. But, thanks to the tremendous efforts of &lt;a class="reference external" href="http://alexgaynor.net/"&gt;Alex Gaynor&lt;/a&gt; and &lt;a class="reference external" href="http://cecinestpasun.com/"&gt;Russell Keith-Magee&lt;/a&gt; Django now has &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/db/multi-db/"&gt;robust multi-db support&lt;/a&gt; built in. With a 'default' and 'replica' database configured, you can easily perform a read operation on your replica with the 'using' method:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;replica&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;mmalone&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Master-slave replication is pretty trivial to setup, but it has its own peculiarities, the most insidious being slave lag. Again, write operations are committed to the master database before they're sent along to the replica asynchronously. That means there is a period of time after a successful write operation, but before the replica has received the update, where the replica will be out of sync.&lt;/p&gt;
&lt;p&gt;Initially, it seems like slave lag shouldn't be much of an issue. Lag is usually only a few hundred milliseconds. But with the common &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Post/Redirect/Get"&gt;POST/Redirect/GET&lt;/a&gt; pattern used on the web, lag can be painfully obvious. Since GET operations often follow immediately after a POST, there's a good chance the data a user POSTs won't be replicated in time. The simplest solution to this problem is to force read operations to go to the master for a little while after a user performs a write operation. At Pownce we flagged users in memcache after a successful write and pinned them to the master database until the flag expired (usually a few seconds). It's not the prettiest solution in the world, but it worked.&lt;/p&gt;
&lt;p&gt;More sophisticated solutions exist. MySQL can actually report the current slave lag, so you could generate a more accurate lag estimate and use that to adjust the period of time users are pinned to the master. Unfortunately, lag is likely to spike when your app is under heavy load. And if you're experiencing heavy load you probably don't want to start sending more queries to your master database. So you need to decide: would you rather guarantee consistency, send queries to the master, and risk overloading it and taking your whole site down; or would you prefer to send queries to your slave database despite lag, and risk returning inconsistent results to your users. Keep this dichotomy in mind, we'll be revisiting it shortly.&lt;/p&gt;
&lt;p&gt;Since every replica has to perform every write operation, you'll start to see decreasing returns as the app's write volume picks up. At some point write volume will be too much for a single machine to handle. Assuming you decide to stick with a relational database, the only option is to start splitting your dataset into pieces. This process is called &amp;quot;sharding&amp;quot; or &amp;quot;federation&amp;quot;, and it's a technique that's employed by most large scale web properties including &lt;a class="reference external" href="http://danga.com/words/2007_yapc_asia/yapc-2007.pdf"&gt;livejournal&lt;/a&gt;, &lt;a class="reference external" href="http://mysqldba.blogspot.com/2008/04/mysql-uc-2007-presentation-file.html"&gt;Flickr&lt;/a&gt;, &lt;a class="reference external" href="http://about.digg.com/blog/digg-database-architecture"&gt;Digg&lt;/a&gt;, Twitter, Facebook, YouTube, and Wikipedia, among many others.&lt;/p&gt;
&lt;p&gt;Conceptually, federation isn't that hard: you take a large database, and you split it up into a cluster of smaller databases running on different machines. You can partition your data vertically, moving entire tables onto their own nodes, or horizontally, splitting a large table onto several nodes. More likely, you'll combine these approaches to suit your particular needs. Throw in a bit of &lt;a class="reference external" href="http://www.tomkleinpeter.com/2008/03/17/programmers-toolbox-part-3-consistent-hashing/"&gt;consistent hashing&lt;/a&gt;, or a central records database to point you to the correct shard, along with some &lt;a class="reference external" href="http://gist.github.com/117292"&gt;mechanism for generating primary keys&lt;/a&gt; (autoincrement won't work when you have multiple databases) and you're in business until it's time to &lt;a class="reference external" href="http://wiki.github.com/voldemort/voldemort/voldemort-rebalancing"&gt;rebalance&lt;/a&gt; nodes. Of course in practice all of this is far more complicated than I'm letting on. Regardless, the new Django multi-db functionality should give you all of the tools you need to implement your sharding scheme.&lt;/p&gt;
&lt;p&gt;Once you've federated your database, you'll lose the ability to join across shards and will no longer be able to rely on transactions to guarantee the integrity of your data. You can design an architecture that retains some of the atomicity, isolation, and consistency characteristics of a typical relational datastore. But at a certain scale you'll have to relax some of these constraints. Here's why: there are three important characteristics of shared data systems that are deployed in distributed environments like the web:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;em&gt;Consistency&lt;/em&gt;: every node in the system contains the same data (e.g., replicas are never out of date).&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Availability&lt;/em&gt;: every request to a non-failing node in the system returns a response.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Partition Tolerance&lt;/em&gt;: system properties (consistency and/or availability) hold even when the system is partitioned and messages are lost.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;But here's the rub: you can only have two. &lt;a class="reference external" href="http://www.cs.berkeley.edu/~brewer/"&gt;Eric Brewer&lt;/a&gt; popularized this theory in 2000 at &lt;a class="reference external" href="http://www.podc.org/podc2000/"&gt;Principles of Distributed Computing&lt;/a&gt;, and it was later &lt;a class="reference external" href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.20.1495&amp;amp;rep=rep1&amp;amp;type=pdf"&gt;formally proven&lt;/a&gt; and dubbed the CAP Theorem. It's simple enough to prove to yourself without the rigor of an academic publication &amp;#8212; assume we have two nodes: A, and B. They're a master-master pair that replicate one another's data. Now suppose a write occurs on node A. Ordinarily, node A would immediately pass the new value on to node B, and wouldn't return a successful response to the client until it had done so (probably using a &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Two-phase_commit_protocol"&gt;two-phase commit&lt;/a&gt; protocol). But if there's a network partition that splits nodes A and B this is impossible. Either node A fails to record the new data, which means the system is no longer available, or it updates its local copy and returns success without notifying node B, which means the system is no longer consistent. Them's the breaks.&lt;/p&gt;
&lt;p&gt;The relational database systems we're all used to were built with consistency as their primary goal. But at scale our system needs to have high availability. And as we add more servers the possibility of a network partition becomes an inevitability. So how do we reconcile this situation? Well, we've already discussed several methods of loosening the consistency constraints imposed by traditional database systems: caching, replication, and sharding are all essentially kludges that trade consistency for availability and partition tolerance. It'd be nice if we didn't have to re-invent the wheel though.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="nosql"&gt;
&lt;h1&gt;NoSQL&lt;/h1&gt;
&lt;p&gt;Over the last couple of years a number of specialized databases have emerged: graph databases, document databases, key-value stores, and various combinations. Collectively, this new class of non-relational datastore has been dubbed &amp;quot;&lt;a class="reference external" href="http://en.wikipedia.org/wiki/NoSQL"&gt;NoSQL&lt;/a&gt;.&amp;quot; It's a broad category, and the name is not entirely accurate since SQL is rather orthogonal to their goals, but I digress. Many of these systems are based on some combination of Google's &lt;a class="reference external" href="http://labs.google.com/papers/bigtable.html"&gt;Bigtable&lt;/a&gt; and Amazon's &lt;a class="reference external" href="http://s3.amazonaws.com/AllThingsDistributed/sosp/amazon-dynamo-sosp2007.pdf"&gt;Dynamo&lt;/a&gt;, which are well documented (albeit closed-source and proprietary) examples of the sort of operation that a horizontally scalable data store can power.&lt;/p&gt;
&lt;p&gt;Instead of federating your MySQL database, it might make sense to move some data to a &lt;a class="reference external" href="http://incubator.apache.org/cassandra/"&gt;Cassandra&lt;/a&gt; cluster, for example. If you're using a relational database to store data blobs that are only fetched by key, something like &lt;a class="reference external" href="http://code.google.com/p/redis/"&gt;Redis&lt;/a&gt; or &lt;a class="reference external" href="http://1978th.net/tokyotyrant/"&gt;Tokyo Tyrant&lt;/a&gt; should improve throughput considerably. And if you'd like to continue querying your dataset, but want the improved availability and increased capacity of a distributed system, you might check out &lt;a class="reference external" href="http://couchdb.apache.org/"&gt;CouchDB&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unfortunately, none of these solutions integrate tightly with Django. The Django ORM was designed specifically to interact with relational databases. In fact, the &lt;a class="reference external" href="http://www.python.org/dev/peps/pep-0249/"&gt;Python Database API Specification&lt;/a&gt; assumes a datastore that is relational and supports SQL. So taking advantage of these new tools means you can't use the ORM, and you'll probably have to rewrite any reusable apps that you're using.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-future"&gt;
&lt;h1&gt;The Future&lt;/h1&gt;
&lt;p&gt;As Django continues to mature, I'd love to see a low-level database API develop that doesn't assume a relational datastore. I'm not sure exactly what this would look like, but get, save, and delete operations by key are pretty universal. So a basic API wrapping that functionality would be a great start. It'd be terrific if models built on this API integrated with the admin, and core reusable Django apps like contrib.auth utilized it, instead of the less universal ORM.&lt;/p&gt;
&lt;p&gt;At &lt;a class="reference external" href="http://euro.djangocon.org/"&gt;Euro DjangoCon 2009&lt;/a&gt;, &lt;a class="reference external" href="http://stu.mp/"&gt;Joe Stump&lt;/a&gt; gave a keynote presentation about &amp;quot;&lt;a class="reference external" href="http://stu.mp/presentations/EuroDjangoCon/2009/Rethinking_the_Stack.key.zip"&gt;rethinking the stack&lt;/a&gt;.&amp;quot; During that presentation, he encouraged Django developers to stop thinking of Django as a framework, and to start thinking of it as &amp;quot;command and control&amp;quot; for your web application. I think Django has a leg-up on the competition in this area. The Django admin is a powerful tool without a corollary in other environments. In the future, it would be great have core apps that integrate with, and provide insight into, mail delivery, queuing, and remote web services too.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-end"&gt;
&lt;h1&gt;The End&lt;/h1&gt;
&lt;p&gt;So there's no magic here: building a really big application is a really big commitment. You'll need to think carefully about your architecture and plan for future needs. But as long as you keep an eye on your stats, keep your caches primed, your queues short, and your data tier distributed, your site should be able to handle whatever the net can throw at it. Guess it's time to start working on that business model.&lt;/p&gt;
&lt;p&gt;Honestly though, it's been a pleasure watching the Django community grow and thrive over the last two years. And I'm extremely excited to see what's in store for the next two. There's one thing I'm sure of though: it's going to be a nightmare keeping my &amp;quot;scaling Django&amp;quot; notes up to date.&lt;/p&gt;
&lt;p&gt;I am happy report that I can finally say, without stipulation or hesitation, something I've been unable to say up until this point: Django 1.2 is capable of operating at web-scale.&lt;/p&gt;
&lt;/div&gt;
</summary></entry><entry><title>Django Testing Improvements</title><link href="http://djangoadvent.com/1.2/django-testing-improvements/" rel="alternate" /><updated>2010-02-24T00:00:00-11:00</updated><author><name>Eric Holscher</name><uri>http://ericholscher.com</uri></author><id>http://djangoadvent.com/1.2/django-testing-improvements/</id><summary type="html">&lt;p&gt;The testing realm in Django is mostly composed of two audiences: contributors to Django itself (running the substantial existing suite of tests) and application developers with their own suite of tests. Django 1.2 brings a few improvements to the testing infrastructure aimed at making the tester's life a little bit easier in both of these scenarios.&lt;/p&gt;
&lt;div class="section" id="multiple-databases"&gt;
&lt;h1&gt;Multiple Databases&lt;/h1&gt;
&lt;div class="section" id="what-changed"&gt;
&lt;h2&gt;What Changed&lt;/h2&gt;
&lt;p&gt;The introduction of multiple database support touched many parts of Django, and the testing framework is no exception.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="django-developers"&gt;
&lt;h2&gt;Django Developers&lt;/h2&gt;
&lt;p&gt;Django's tests now require a more detailed settings file in order to pass. If you run the test suite with your old settings file, which simply defined a single database, the MultiDB tests will fail (22 of them, to be exact). An example of the minimum settings file needed is supplied below. As of the Django Pycon sprint, this file is actually shipped with Django itself. So in order to run the Django test suite on SQLite, you don't have to touch your filesystem!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;DATABASES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;default&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;&amp;#39;ENGINE&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;django.db.backends.sqlite3&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;other&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;&amp;#39;ENGINE&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;django.db.backends.sqlite3&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;&amp;#39;TEST_NAME&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;other_db&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To run the Test Suite, &lt;tt class="docutils literal"&gt;cd&lt;/tt&gt; into the &lt;cite&gt;tests&lt;/cite&gt; directory of your Django checkout, and run the following command:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
./runtests.py --settings=test_sqlite
&lt;/pre&gt;
&lt;p&gt;This will run with the supplied &lt;cite&gt;test_sqlite.py&lt;/cite&gt; file, which is identical to the above settings file.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="app-developers"&gt;
&lt;h2&gt;App Developers&lt;/h2&gt;
&lt;p&gt;This only really affects you if your application expects to be deployed against a multiple database environment. The Django documentation on testing has specific topics about &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/testing/#testing-master-slave-configurations"&gt;Testing Master/Slave setups&lt;/a&gt;, which allows you to use the &lt;tt class="docutils literal"&gt;TEST_MIRROR&lt;/tt&gt; setting on a slave database and have it mirror the master for tests. The Django TestCase also added the  &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/testing/#multi-database-support"&gt;multidb&lt;/a&gt; attribute, which will flush all databases before running the test cases inside. By default, Django only flushes the default database, as an optimization.&lt;/p&gt;
&lt;p&gt;However, unless you are specifically writing against a multible database environment, you should be able to safely ignore these changes.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="fail-fast-and-fail-early"&gt;
&lt;h1&gt;Fail fast and fail early&lt;/h1&gt;
&lt;p&gt;If you are running the test suite, it is presumably because you expect it to pass. So when you run the suite and see that a test has failed, more often than not, that is all the information that you need to know. If you have a long suite, you don't want to have to wait for it to finish running before you see the error, since that error is what you care about.&lt;/p&gt;
&lt;div class="section" id="id1"&gt;
&lt;h2&gt;What Changed&lt;/h2&gt;
&lt;p&gt;As of &lt;a class="reference external" href="http://code.djangoproject.com/changeset/11843"&gt;Revision 11843&lt;/a&gt;, Django added a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--failfast&lt;/span&gt;&lt;/tt&gt; option to the test runner. When this option is selected, Django will exit the test run once it encounters a failure. This is useful for certain work flows, including some forms of Test Driven Development, where you expect tests to fail often, and don't want to run through the entire test to see what has failed.&lt;/p&gt;
&lt;p&gt;In Django 1.1 and before, if you were to &amp;lt;Ctrl+C&amp;gt; and cancel a test run, you would be treated with a nice ugly traceback with no information.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="o"&gt;............^&lt;/span&gt;&lt;span class="n"&gt;CTraceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;./manage.py&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;execute_manager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;/Users/eric/svn-clones/django/template/__init__.py&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;285&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;
    &lt;span class="n"&gt;compiled_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compile_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ne"&gt;KeyboardInterrupt&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When you try the same trick as of &lt;a class="reference external" href="http://code.djangoproject.com/changeset/12034"&gt;Revision 12034&lt;/a&gt;, the current test will finish running and exit gracefully.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;.....................^C &amp;lt;Test run halted by Ctrl-C&amp;gt; .
----------------------------------------------------------------------
Ran 22 tests in 1.308s

OK
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This allows you to get the same benefits from the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--failfast&lt;/span&gt;&lt;/tt&gt; option, even if you forget to set it at the beginning. Once you see a test fail, you can simply &lt;tt class="docutils literal"&gt;Ctrl+C&lt;/tt&gt;, and you will get your failing test output back out.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="id2"&gt;
&lt;h2&gt;Django Developers&lt;/h2&gt;
&lt;p&gt;This is important for developing against the Django source tree because the Django test suite takes a long time to run. The full suite can take upwards of 10 minutes, especially for bigger databases like Oracle. Previously, if you saw a failure you would just have to wait until the tests had finished running to be able to see the actual error. Breaking out early would result in the loss of the data you were after! Now you will be able to easily bail out on the first failure, or if you're forgotten the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--failfast&lt;/span&gt;&lt;/tt&gt; option, a simple &lt;tt class="docutils literal"&gt;Ctrl+C&lt;/tt&gt; will do it for you.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="id3"&gt;
&lt;h2&gt;App Developers&lt;/h2&gt;
&lt;p&gt;This is important for integrating testing into your work flow. One of the main ideas behind testing is that you should be running your tests while you are developing, and see if you are making errors while you are writing the code.&lt;/p&gt;
&lt;p&gt;Adding the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--failfast&lt;/span&gt;&lt;/tt&gt; argument to whatever mechanism you have to run your tests after changes, will allow you to work faster when things break. You will be alerted right away to breakages in your code, and be able to fix them.&lt;/p&gt;
&lt;p&gt;There are a number of other features that would be nice to have in this realm as well. Being able to run your full test suite, and then only run the failing tests from the previous run is another optimization here. This will hopefully make it into Django 1.3, or be realized as a stand-alone app before then.&lt;/p&gt;
&lt;p&gt;There are also a number of efforts to integrate your Django tests with nose. So if you haven't started writing your test suite, looking at &lt;a class="reference external" href="http://github.com/jbalogh/django-nose/"&gt;django-nose&lt;/a&gt; or &lt;a class="reference external" href="http://devel.almad.net/trac/django-sane-testing/"&gt;django-sane-testing&lt;/a&gt; might make sense, as nose already has a lot of these features built in.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="keepin-it-classy"&gt;
&lt;h1&gt;Keepin’ it classy&lt;/h1&gt;
&lt;p&gt;The (arguably) largest improvement to Django's testing infrastructure in 1.2 is class-based test runners. This is a big deal in that it allows for easier subclassing of the current test runner; anyone who wants to change how Django's tests are run has a much easier job to do.&lt;/p&gt;
&lt;div class="section" id="id4"&gt;
&lt;h2&gt;What Changed&lt;/h2&gt;
&lt;p&gt;As of &lt;a class="reference external" href="http://code.djangoproject.com/changeset/12255"&gt;Revision 12255&lt;/a&gt;, the default test runner for Django is now a class. There is code that will detect if you are trying to pass in a 1.1-style function based runner, and do the appropriate thing. However, you should try to update custom test runners to the new style, because it will result in being less code and more maintanable.&lt;/p&gt;
&lt;p&gt;This is only really applicable to application developers, because if you are running the Django test suite, you should be using the official Django test runner.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="an-example"&gt;
&lt;h2&gt;An example&lt;/h2&gt;
&lt;p&gt;In my &lt;a class="reference external" href="http://github.com/ericholscher/pony_utils"&gt;Pony Utils&lt;/a&gt; project, I wanted to create my own &lt;a class="reference external" href="http://github.com/ericholscher/pony_utils/blob/master/pony_utils/django/test_runner.py"&gt;test runner&lt;/a&gt;, and pre-1.2, that required me to copy 60 lines of code, only to edit a few (line 60). The &lt;a class="reference external" href="http://code.djangoproject.com/browser/django/trunk/django/test/simple.py?rev=12375#L300"&gt;run_tests function&lt;/a&gt; in Django is now 7 lines of code, which calls out to other methods. These other methods are easy to subclass in your own test runner, overriding only the parts needed to get the desired behavior.&lt;/p&gt;
&lt;p&gt;The &lt;a class="reference external" href="http://github.com/ericholscher/pony_utils/commit/50355eaab2ae42e327a06380d975fae9ab33e19b"&gt;diff&lt;/a&gt; of the new and old show the changed lines of code. However, this really should be done in the &lt;tt class="docutils literal"&gt;suite_result&lt;/tt&gt; function on the test runner class, since I only want to modify how the results of the tests are sent. This shows a place where the design could be improved.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="the-early-djangonaut-gets-the-pony"&gt;
&lt;h1&gt;The early Djangonaut gets the Pony&lt;/h1&gt;
&lt;p&gt;Testing pre-release software allows users to catch bugs and find use cases that the core developers haven't thought about &amp;#8212; and address them before they are baked into a production release that must be supported. If a new feature isn't well tested before release, Django is stuck supporting that functionality for at least three releases going forward, and everyone gets suboptimal behavior.&lt;/p&gt;
&lt;p&gt;When I was writing this article, I found a way that the new class based test runner could be better used. The &lt;tt class="docutils literal"&gt;suite_result&lt;/tt&gt; function of the test runner wasn't being passed the actual suite to report the results on. The default Django functionality here is just to report the number of errors and exit, but I wanted to do more, and needed the suite. So I filed a &lt;a class="reference external" href="http://code.djangoproject.com/ticket/12932"&gt;ticket&lt;/a&gt;, with my example use case that wasn't supported, and hoped for the best.&lt;/p&gt;
&lt;p&gt;Luckily this happened during the Pycon sprints, and Russell Keith-Magee accepted the ticket and &lt;a class="reference external" href="http://code.djangoproject.com/changeset/12487"&gt;patched Django&lt;/a&gt; within a day! This case is a great example of how using the pre-release version of Django can lead to making the software better.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="thanks-for-reading"&gt;
&lt;h1&gt;Thanks for reading&lt;/h1&gt;
&lt;p&gt;I hope this article has made testing more enlightening for you, and has helped highlight the new features in the 1.2 release. Now go out and use them to improve the quality of your code, and Django itself!&lt;/p&gt;
&lt;/div&gt;
</summary></entry><entry><title>jQuery in the Admin</title><link href="http://djangoadvent.com/1.2/jquery-admin/" rel="alternate" /><updated>2010-02-23T00:00:00-11:00</updated><author><name>Zain Memon</name><uri>http://inzain.net/</uri></author><id>http://djangoadvent.com/1.2/jquery-admin/</id><summary type="html">&lt;p&gt;&lt;a class="reference external" href="http://code.djangoproject.com/changeset/12297"&gt;Changeset r12297&lt;/a&gt; dropped a bomb on everyone: a new file in the &lt;tt class="docutils literal"&gt;django/contrib/admin/media/js&lt;/tt&gt; directory called &lt;tt class="docutils literal"&gt;jquery.js&lt;/tt&gt;. This change ushers in a new era for the Django admin; an era of fancy new features, pretty widgets, and better usability.&lt;/p&gt;
&lt;div class="section" id="the-case-for-jquery"&gt;
&lt;h1&gt;The case for jQuery&lt;/h1&gt;
&lt;p&gt;Despite being discussed in the past, integration of jQuery into the admin wasn't on the map until the GSoC &lt;a class="reference external" href="http://groups.google.com/group/django-developers/browse_thread/thread/1edf77c9c8b1101d/4ecda5e4c982c7e1"&gt;admin-ui proposal&lt;/a&gt; this summer, which suggested some UI-heavy features that would be difficult without the use of a framework.&lt;/p&gt;
&lt;p&gt;It’s easy to see the need for a Javascript framework in the admin. Raw Javascript in any decently sized project slowly approaches the size and complexity of a framework. That process becomes a minefield of dealing with cross-browser issues, workarounds, and normalization; a framework short-circuits that pain and lets developers focus on building cool stuff. We live in the future, and there’s just no good reason to write Javascript straight to the DOM APIs when we could be adding useful functionality (with fewer bugs) instead.&lt;/p&gt;
&lt;p&gt;It’s also easy to see why jQuery is the framework of choice: jQuery has &lt;a class="reference external" href="http://www.google.com/trends?q=jquery,+mootools,+dojo,+prototype+js&amp;amp;ctab=0&amp;amp;geo=all&amp;amp;date=all&amp;amp;sort=0"&gt;soundly won&lt;/a&gt; the JS framework wars. Almost 30% of the sites tracked by &lt;a class="reference external" href="http://trends.builtwith.com/javascript/JQuery"&gt;builtwith.com&lt;/a&gt; use jQuery. Picking something else would mean fewer knowledgeable devs, less available code, and a smaller community of support.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="this-doesnt-mean-django-endorses-jquery"&gt;
&lt;h1&gt;This doesn’t mean Django endorses jQuery&lt;/h1&gt;
&lt;p&gt;There's some concern in the community that the inclusion of jQuery appears to be an endorsement of one framework over another &amp;#8212; that's not the case at all.&lt;/p&gt;
&lt;p&gt;Django proper remains blissfully agnostic to toolkit choice. The admin is an optional app designed for end-users, not other developers. Data entry clerks are unaffected by the admin’s tooling, and developers are not constrained by it.&lt;/p&gt;
&lt;p&gt;If you're modifying the Django admin, jQuery stays out of your way. For example, the admin uses &lt;tt class="docutils literal"&gt;jQuery.noConflict()&lt;/tt&gt; to make sure the &lt;tt class="docutils literal"&gt;$&lt;/tt&gt; variable isn’t polluting your namespace, so you can use Prototype’s &lt;tt class="docutils literal"&gt;$()&lt;/tt&gt; in your own widgets without any conflicts. Also, jQuery is only loaded on pages with widgets that require it.&lt;/p&gt;
&lt;p&gt;Your apps can still use whatever makes sense for you. For the Django admin, including a well-tested, proven framework makes more sense than to add even more undocumented, unvetted spaghetti Javascript.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="this-does-mean-djangos-admin-will-grow-much-faster"&gt;
&lt;h1&gt;This does mean Django’s admin will grow much faster&lt;/h1&gt;
&lt;p&gt;The front-end of the admin has stagnated a bit. A perfect storm is brewing for some kick-ass new front-end features: jQuery, a newly (re)appointed &lt;a class="reference external" href="http://groups.google.com/group/django-developers/browse_thread/thread/18bca037f10769e9/50fc65fe85746197"&gt;design czar&lt;/a&gt;, and a general focus in the community on better usability.&lt;/p&gt;
&lt;p&gt;Django 1.2 mainly focused on laying the groundwork for future admin-ui improvements and most visible changes won't be felt until Django 1.3 and later. However, a few things did make it in.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="new-features"&gt;
&lt;h1&gt;New features&lt;/h1&gt;
&lt;p&gt;One of the first jQuery features in the admin is the dynamic addition of new inlines. For a demo of this functionality, check out this screencast:&lt;/p&gt;
&lt;video width="624" height="464" controls="controls" autobuffer="autobuffer"&gt;
        &lt;source src="http://djangoadvent.s3.amazonaws.com/advent/002/inlines_624x464.mp4" type='video/mp4; codecs="avc1.42E01E"'&gt;
        &lt;source src="http://djangoadvent.s3.amazonaws.com/advent/002/inlines_624x464.ogv" type='video/ogg; codecs="theora"'&gt;
        &lt;object width="624" height="488" type="application/x-shockwave-flash" data="http://djangoadvent.s3.amazonaws.com/advent/002/player.swf?image=http://djangoadvent.s3.amazonaws.com/advent/002/inlines_poster.png&amp;amp;file=http://djangoadvent.s3.amazonaws.com/advent/002/inlines_624x464.mp4"&gt;
                &lt;param name="movie" value="http://djangoadvent.s3.amazonaws.com/advent/002/player.swf?image=http://djangoadvent.s3.amazonaws.com/advent/002/inlines_poster.png&amp;amp;file=http://djangoadvent.s3.amazonaws.com/advent/002/inlines_624x464.mp4" /&gt;
                &lt;img src="http://djangoadvent.s3.amazonaws.com/advent/002/inlines_poster.png" width="624" height="464" alt="Dynamic Admin Inlines"
                     title="No video playback capabilities, please download the video below" /&gt;
        &lt;/object&gt;
&lt;/video&gt;

&lt;aside&gt;Download Video: &lt;a href="http://djangoadvent.s3.amazonaws.com/advent/002/inlines_624x464.mp4"&gt;MP4&lt;/a&gt; | &lt;a href="http://djangoadvent.s3.amazonaws.com/advent/002/inlines_624x464.ogv"&gt;Theora (Ogg)&lt;/a&gt;&lt;/aside&gt;&lt;p&gt;A lot of implemented features missed the cut for Django 1.2, like drag-and-drop reordering of inlines for models with an ordering field, and an autocomplete widget for Foreign Key and M2M relations to be used instead of the select drop-down (or raw_id_fields). Those features (and others) will most likely land in Django 1.3.&lt;/p&gt;
&lt;p&gt;These are exciting times for the users of the Django admin. There’s already some admin hotness in 1.2, and it’s only going to get better by the time 1.3 ships. jQuery it up!&lt;/p&gt;
&lt;/div&gt;
</summary></entry><entry><title>If Gets Smart</title><link href="http://djangoadvent.com/1.2/if-gets-smart/" rel="alternate" /><updated>2010-02-22T00:00:00-11:00</updated><author><name>Chris Beaven</name><uri>http://www.saobart.com/</uri></author><id>http://djangoadvent.com/1.2/if-gets-smart/</id><summary type="html">&lt;p&gt;Ah, the humble &lt;tt class="docutils literal"&gt;{% if %}&lt;/tt&gt; tag. The cornerstone of Django template display logic.&lt;/p&gt;
&lt;p&gt;Every beginner working with Django 1.1 or below will most likely have tripped over the fact that the &lt;tt class="docutils literal"&gt;{% if %}&lt;/tt&gt; template tag only supports basic boolean logic.&lt;/p&gt;
&lt;p&gt;Restricting the tag to only evaluate if a variable is &amp;quot;true&amp;quot; (i.e. exists, is not empty, and is not a false boolean value) was a purposeful restriction to the template system to encourage users to separate their presentation and business logic.&lt;/p&gt;
&lt;p&gt;As a weekend project, I challenged myself to write a smarter if tag and then released it as a &lt;a class="reference external" href="http://www.djangosnippets.org/snippets/1350/"&gt;django snippet&lt;/a&gt;, which quickly gained popularity. About eight months later, replacing the if tag was proposed for Django 1.2 and championed by Luke Plant.&lt;/p&gt;
&lt;div class="section" id="so-what-s-new-mr-if"&gt;
&lt;h1&gt;So what's new, Mr If?&lt;/h1&gt;
&lt;p&gt;From Django 1.2, the &lt;tt class="docutils literal"&gt;{% if %}&lt;/tt&gt; template tag has been extended to support basic Pythonic logic, giving you the ability do the following types of things:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;you.friends.count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;You&amp;#39;re popular!&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;endif&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;country&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;NZ&amp;quot;&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;Come and visit New Zealand!&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;endif&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can still use template filters with this new logic. This gives you the ability for useful statements like &lt;tt class="docutils literal"&gt;{% if messages|length &amp;gt; 3 &lt;span class="pre"&gt;%}...{%&lt;/span&gt; endif %}&lt;/tt&gt;.&lt;/p&gt;
&lt;div class="section" id="if-not-python"&gt;
&lt;h2&gt;If not Python&lt;/h2&gt;
&lt;p&gt;Remember this isn't Python: you won't have access to the &lt;tt class="docutils literal"&gt;None&lt;/tt&gt; builtin or any python builtin functions.&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;{% if movie == None %}&lt;/tt&gt; won't work. But if you need more than &lt;tt class="docutils literal"&gt;{% if not movie %}&lt;/tt&gt; then you're doing it wrong anyway.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="mixing-boolean-logic"&gt;
&lt;h2&gt;Mixing boolean logic&lt;/h2&gt;
&lt;p&gt;The tag also now handles mixed &lt;tt class="docutils literal"&gt;and&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;or&lt;/tt&gt; boolean logic. But I'd encourage you to avoid using it regularly - it quickly leads to confusion. For example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;staff&lt;/span&gt; &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="nv"&gt;author&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="nv"&gt;expired&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;edit_url&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Edit this&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;endif&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What happens under certain circumstances would be unclear to designers (&amp;quot;if the user is staff, but has also expired, what happens then?&amp;quot;). It would be much clearer calculating this in the view and passing through an &lt;tt class="docutils literal"&gt;editable&lt;/tt&gt; context variable. Lets come back to this in a moment.&lt;/p&gt;
&lt;p&gt;If you need a different order of evaluation than Python's operator precedence, use multiple &lt;tt class="docutils literal"&gt;if&lt;/tt&gt; tags &amp;#8212; using parentheses are not supported.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="missing-variables"&gt;
&lt;h2&gt;Missing variables&lt;/h2&gt;
&lt;p&gt;An important consideration is what happens when a context variable does not exist. It has been left simple: it equates to &lt;tt class="docutils literal"&gt;None&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="digging-deep"&gt;
&lt;h1&gt;Digging deep&lt;/h1&gt;
&lt;p&gt;Let's have a look at what's going on behind the scenes. If you're &lt;em&gt;not&lt;/em&gt; one of those people that likes to pull apart radios, you can skip this section.&lt;/p&gt;
&lt;p&gt;The parser in the snippet was simple; it worked but it wasn't very deep. However, the only major bug found in the snippet was with boolean operators not having precidence over comparison:&lt;/p&gt;
&lt;blockquote&gt;
&lt;tt class="docutils literal"&gt;x or x == 0&lt;/tt&gt; was being parsed as &lt;tt class="docutils literal"&gt;(x or x) == 0&lt;/tt&gt; instead of
&lt;tt class="docutils literal"&gt;x or (x == 0)&lt;/tt&gt;.&lt;/blockquote&gt;
&lt;p&gt;While this was able to be fixed, I was never really happy with the parser and Russell Keith-Magee noted this in his review of the submission branch. Luke Plant followed up with a link to an article on a parser implementation titled &lt;a class="reference external" href="http://effbot.org/zone/simple-top-down-parsing.htm"&gt;Simple Top-down Parsing in Python&lt;/a&gt; by Fredrik Lundh.&lt;/p&gt;
&lt;p&gt;The snippet still takes a naive approach to parsing complex logical expressions. In the snippet, &amp;quot;A or B and C&amp;quot; is parsed as &amp;quot;(A or B) and C&amp;quot;, not the pythonic way &amp;quot;A or (B and C)&amp;quot; (giving operator precedence to AND over OR).&lt;/p&gt;
&lt;p&gt;This better parser implementation was used for the patch with the benefits of correctly implementing full operator precedence. It weights operators (starting from highest precidence) in the same order as Python:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;or&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;and&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;not&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;in&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;comparisons (&lt;tt class="docutils literal"&gt;==&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;!=&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&amp;lt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&amp;gt;&lt;/tt&gt;,``&amp;lt;=``, &lt;tt class="docutils literal"&gt;&amp;gt;=&lt;/tt&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;div class="section" id="too-much-time-challenge"&gt;
&lt;h2&gt;&amp;quot;Too much time?&amp;quot; challenge&lt;/h2&gt;
&lt;p&gt;Read through that &lt;a class="reference external" href="http://effbot.org/zone/simple-top-down-parsing.htm"&gt;Simple Top-down Parsing in Python&lt;/a&gt; article once or twice, trying to understand exactly what's going on and then... build the parser yourself.&lt;/p&gt;
&lt;p&gt;If you need to, come back to the article again to give yourself some tips. The challenge is to re-implement the functionality from the overall ideas rather than the specific implementation given there.&lt;/p&gt;
&lt;p&gt;Being a bit of a sadist, I gave myself this challenge after reading the first paragraph. &lt;a class="reference external" href="http://gist.github.com/250128"&gt;Here's my take&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="just-because-you-can"&gt;
&lt;h1&gt;Just because you can...&lt;/h1&gt;
&lt;p&gt;There's a time and a place for using the new functionality of the tag. Keep your presentation and business logic separated. Perhaps that comparison would be better pushed to your view? Or a model method?&lt;/p&gt;
&lt;p&gt;A lot has been written about the importance of logic separation, but here are a few reasons:&lt;/p&gt;
&lt;div class="section" id="being-nice-to-designers"&gt;
&lt;h2&gt;Being nice to designers&lt;/h2&gt;
&lt;p&gt;Keeping complex logic out of your templates allows your designers to focus on what they are good at without having to worry about complexities like operator precedence or advanced boolean logic.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="separation-of-thought-and-providing-readable-code"&gt;
&lt;h2&gt;Separation of thought, and providing readable code&lt;/h2&gt;
&lt;p&gt;It is easier to read business logic that is not intermingled with presentation logic. Similarly, it is easier to look at the presentation of a screen or read html code without having to sift through the database and security logic.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="endif"&gt;
&lt;h1&gt;endif&lt;/h1&gt;
&lt;p&gt;There's only so much I can ramble on about a basic logic tag, so let us finish here. Thanks to Luke Plant for his hard work in getting this ready for Django 1.2.&lt;/p&gt;
&lt;p&gt;Remember, the official documentation covers all new functionality. Here's a link to the &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/ref/templates/builtins/#if"&gt;if tag&lt;/a&gt; section for you.&lt;/p&gt;
&lt;/div&gt;
</summary></entry><entry><title>Deploying a Django Site using FastCGI</title><link href="http://djangoadvent.com/1.2/deploying-django-site-using-fastcgi/" rel="alternate" /><updated>2010-02-19T00:00:00-11:00</updated><author><name>Eric Florenzano</name><uri>http://www.eflorenzano.com/</uri></author><id>http://djangoadvent.com/1.2/deploying-django-site-using-fastcgi/</id><summary type="html">&lt;p&gt;When developing a site with Django, it's so easy to simply pop open a console
and type:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;python manage.py runserver
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With that single management command, our admin media files are served properly,
the Python path is set to properly include our project root, and a simple
autoreloading webserver is started on the port that we specify.  It's all so
easy!&lt;/p&gt;
&lt;p&gt;It's no wonder that people are frustrated when it comes to putting their site
into production: there are so many steps in the process, and that makes it
difficult to learn and to get right.  Unsurprisingly, this difficulty has lead
to many articles being written about deploying a Django website.  But almost
all of those articles focus on how to deploy a site using Apache and
&lt;a class="reference external" href="http://code.google.com/p/modwsgi/"&gt;mod_wsgi&lt;/a&gt; or &lt;a class="reference external" href="http://www.modpython.org/"&gt;mod_python&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are some times, however, where Apache is not the ideal solution.  Maybe
it's that our &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Virtual_private_server"&gt;VPS&lt;/a&gt; only has 256MB of RAM.  Maybe it's that we want to avoid
the added complexity of Apache in our setup.  Or maybe it's that we simply
don't like Apache.  For these reasons, we might turn our attention to
&lt;a class="reference external" href="http://www.fastcgi.com/drupal/"&gt;FastCGI&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="first-things-first"&gt;
&lt;h1&gt;First Things First&lt;/h1&gt;
&lt;p&gt;Before we can get started on doing this deployment, we need to make sure that
we've gotten the base of our system set up.  Firstly, we'll need a server on
which to deploy our app.  This can really be any server and operating system,
but for the sake of simplicity we'll be assuming an Ubuntu-flavored Linux as a
target.&lt;/p&gt;
&lt;p&gt;Let's get the basics out of the way, including some compilers, development
headers for Python, and &lt;a class="reference external" href="http://pypi.python.org/pypi/setuptools"&gt;setuptools&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo apt-get install build-essential python-dev python-setuptools
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a class="reference external" href="http://nginx.org/"&gt;Nginx&lt;/a&gt; should also be installed, as it will act as our webserver.  We can do
this with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo apt-get install nginx
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We should also have &lt;a class="reference external" href="http://cr.yp.to/daemontools.html"&gt;daemontools&lt;/a&gt; installed, which is a collection of tools
for managing services.  We're going to be using it to ensure that our service
stays up and running (or at least comes back to life), even in the event of
failure or server restart.  To install daemontools, type:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo apt-get install daemontools
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Unfortunately, the package for daemontools in Ubuntu could use a bit of work,
so we have to do a bit more ourselves to finish the installation so that it
automatically runs at boot time.  First, create a file at
&lt;tt class="docutils literal"&gt;/etc/event.d/svscanboot&lt;/tt&gt; with these contents:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;start on runlevel 2
start on runlevel 3
start on runlevel 4
start on runlevel 5

stop on runlevel 0
stop on runlevel 1
stop on runlevel 6

respawn
&lt;span class="nb"&gt;exec&lt;/span&gt; /usr/bin/svscanboot
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now make a directory at &lt;tt class="docutils literal"&gt;/etc/service&lt;/tt&gt; by running this command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo mkdir /etc/service
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, we kick off the daemontools process by running this command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo initctl start svscanboot
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We're also going to create a new user for our site:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;adduser mysite
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since we want to be able to use the &lt;tt class="docutils literal"&gt;sudo&lt;/tt&gt; command with our user, we'll also
edit &lt;tt class="docutils literal"&gt;/etc/sudoers&lt;/tt&gt;.  Find the line where it says &lt;tt class="docutils literal"&gt;root&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="pre"&gt;ALL=(ALL)&lt;/span&gt; ALL&lt;/tt&gt;,
and underneath that add the line:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;mysite &lt;span class="nv"&gt;ALL&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;ALL&lt;span class="o"&gt;)&lt;/span&gt; ALL
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we'll switch to our new user:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;su - mysite
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That's it for the base of our system.  We're purposefully not covering
database, memcached, mail servers, source control, and other various other base
services because they can vary so much depending on personal preference.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="setting-up-our-python-virtual-environment"&gt;
&lt;h1&gt;Setting up our Python Virtual Environment&lt;/h1&gt;
&lt;p&gt;Now that we have the base of our system installed, we can focus on the fun
stuff.  First we're going to install &lt;a class="reference external" href="http://pypi.python.org/pypi/virtualenv"&gt;virtualenv&lt;/a&gt;, which is a tool for
creating isolated Python environments.  Then we'll use virtualenv to create an
isolated environment for our app.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo easy_install virtualenv
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With our newly-installed copy of virtualenv, we can go ahead and set up a new
virtual environment:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;mkdir ~/virtualenvs
virtualenv ~/virtualenvs/mysite
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We've created a directory in our home by the name of &lt;tt class="docutils literal"&gt;virtualenvs&lt;/tt&gt;, and
inside of that we've created a virtualenv called &lt;tt class="docutils literal"&gt;mysite&lt;/tt&gt;.  Now let's start
using that, and install &lt;a class="reference external" href="http://pypi.python.org/pypi/pip"&gt;pip&lt;/a&gt; to make installing packages easier:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/virtualenvs/mysite/bin/activate
easy_install pip
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we need to make sure that we have a package called &lt;a class="reference external" href="http://trac.saddi.com/flup"&gt;Flup&lt;/a&gt; installed.  This
package is a set of useful tools for dealing with WSGI applications.  Included
in these tools is an adapter for taking a WSGI application and serving it as
FastCGI (and SCGI and AJP...but that's beyond the scope of this article.)
Django requires this to be installed before you can use the &lt;tt class="docutils literal"&gt;runfcgi&lt;/tt&gt;
management command.  Using pip we can easily install this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;pip install flup
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we wanted to use database adapters, imaging libraries, or xml parsers
installed into the system Python path, we would also want to make sure that
those are accessible from our virtualenv by adding a .pth file in the
virtualenv's &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;site-packages&lt;/span&gt;&lt;/tt&gt; directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/usr/lib/python2.6/dist-packages/&amp;quot;&lt;/span&gt; &amp;gt; ~/virtualenvs/mysite/lib/python2.6/site-packages/fix.pth
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The next step is to check out our Django code on the server (obviously git can
be replaced with mercurial, svn, or even something like rsync):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;git clone http://github.com/myusername/mysite.git
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If your project has a &lt;a class="reference external" href="http://pip.openplans.org/requirement-format.html"&gt;pip requirements&lt;/a&gt; file, you can make use of that now:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;pip install -U -r mysite/requirements.txt
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or if you don't have a requirements file, you can install the dependencies
manually as needed (the following is an example):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;pip install -U Django simplejson python-memcached
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="choosing-options-for-our-fastcgi-server"&gt;
&lt;h1&gt;Choosing options for our FastCGI Server&lt;/h1&gt;
&lt;p&gt;Whew!  We've come a long way in getting our system set up, and we haven't even
gotten to the FastCGI part yet.  Never fear, we're ready to do that now.  Let's
decide on what kinds of options we want to set when we start our FastCGI
server.&lt;/p&gt;
&lt;p&gt;The first choice to be made is which concurrency method we want to use:&lt;/p&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;threaded&lt;/tt&gt;:&lt;/dt&gt;
&lt;dd&gt;Running a threaded server will run one single process for all of your HTTP requests, which saves a lot on memory, but all the threads are subject to a single &lt;a class="reference external" href="http://wiki.python.org/moin/GlobalInterpreterLock"&gt;Global Interpreter Lock&lt;/a&gt; (GIL).  This means that performance can be hampered on some CPU-intensive loads.  Note that IO takes place outside of the GIL, so IO-intensive loads shouldn't be affected by it.  Also some Python extensions are deemed to not be &amp;quot;thread safe&amp;quot;, which means that they cannot be used with this concurrency choice.&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;prefork&lt;/tt&gt;:&lt;/dt&gt;
&lt;dd&gt;Running a preforking server will spawn a pool of processes, each with their own separate copy of Django and Python loaded into memory.  This means that it will necessarily use more memory, but it's not subject to the aforementioned problems with the GIL or thread safety.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Let's assume we're interested in FastCGI because we're on a server without a lot
of memory.  Since the prefork method will use more memory, we'll choose the
threaded method instead.&lt;/p&gt;
&lt;p&gt;Now we get to choose some more options about how the server should act under
load:&lt;/p&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;minspare&lt;/tt&gt;:&lt;/dt&gt;
&lt;dd&gt;How many spare processes/threads should the server keep around, at minimum, to be ready and waiting for future requests?&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;maxspare&lt;/tt&gt;:&lt;/dt&gt;
&lt;dd&gt;How many spare processes/threads should the server keep around, at maximum, to be ready and waiting for future requests?&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;maxrequests&lt;/tt&gt; (prefork only):&lt;/dt&gt;
&lt;dd&gt;How many requests will each process serve before it's killed and re-created?  To prevent memory leaks from becoming a problem, it's a good idea to set this.&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;maxchildren&lt;/tt&gt; (prefork only):&lt;/dt&gt;
&lt;dd&gt;How many child processes may be handling requests at any given time?&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;We're running on a small 256MB VPS, so we'll choose some very modest settings
of 2 for &lt;cite&gt;minspare&lt;/cite&gt;, 4 for &lt;cite&gt;maxspare&lt;/cite&gt;, 6 for &lt;cite&gt;maxchildren&lt;/cite&gt;, and 500 for
&lt;cite&gt;maxrequests&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;Finally, we choose our last few settings:&lt;/p&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;host&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;What is the hostname on which to listen for incoming connections?&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;port&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;On which port should we listen for incoming connections?&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;pidfile&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;When the FastCGI server starts up, it will write a file whose contents are a process ID.  This process ID is the &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Process_identifier"&gt;pid&lt;/a&gt; of the master thread/process.  This is the process which will handle OS signals like &lt;a class="reference external" href="http://en.wikipedia.org/wiki/SIGHUP"&gt;SIGHUP&lt;/a&gt;.  This option specifies the location of that file.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;After we've made our choices, we can start our server by running the
&lt;tt class="docutils literal"&gt;runfcgi&lt;/tt&gt; command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;python manage.py runfcgi &lt;span class="nv"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;threaded &lt;span class="nv"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1 &lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8080 &lt;span class="nv"&gt;pidfile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mysite.pid &lt;span class="nv"&gt;minspare&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4 &lt;span class="nv"&gt;maxspare&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30 &lt;span class="nv"&gt;daemonize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that we've added a &lt;tt class="docutils literal"&gt;daemonize=false&lt;/tt&gt; flag--this should always be set (in
this author's opinion, having a daemonize option at all is a design flaw in the
runfcgi command.)  Also note that running this command will result in a
&lt;tt class="docutils literal"&gt;mysite.pid&lt;/tt&gt; file being written out in your project directory, so it's a good
idea to ensure that your source control ignores that file.&lt;/p&gt;
&lt;p&gt;Now that we've verified that our FastCGI server starts up properly, let's quit
out and move on to the next step: using daemontools to run this command and
keep it running in the background at all times.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="having-daemontools-run-our-fastcgi-server"&gt;
&lt;h1&gt;Having Daemontools Run our FastCGI Server&lt;/h1&gt;
&lt;p&gt;Daemontools will look inside all of the subdirectories in the &lt;tt class="docutils literal"&gt;/etc/service&lt;/tt&gt;
directory, and in each one it will look for an executable file named &lt;tt class="docutils literal"&gt;run&lt;/tt&gt;.
If it finds one, it will run that executable and restart it if it dies.  So
let's set up a &lt;tt class="docutils literal"&gt;mysite&lt;/tt&gt; directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo mkdir /etc/service/mysite
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now let's make a little script to run our fastcgi server, use your editor of
choice to write these contents to &lt;tt class="docutils literal"&gt;/etc/service/mysite/run&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="nb"&gt;source&lt;/span&gt; /home/mysite/virtualenvs/mysite/bin/activate
&lt;span class="nb"&gt;cd&lt;/span&gt; /home/mysite/mysite
&lt;span class="nb"&gt;exec &lt;/span&gt;envuidgid mysite python manage.py runfcgi &lt;span class="nv"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;threaded &lt;span class="nv"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1 &lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8080 &lt;span class="nv"&gt;pidfile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mysite.pid &lt;span class="nv"&gt;minspare&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4 &lt;span class="nv"&gt;maxspare&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30 &lt;span class="nv"&gt;daemonize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There's nothing tricky about this--first we make sure we're in the correct
virtualenv, then we change directory to the mysite project directory, and then
we run the &lt;tt class="docutils literal"&gt;runfcgi&lt;/tt&gt; command that we discussed earlier.  The &lt;tt class="docutils literal"&gt;envuidgid
mysite&lt;/tt&gt; part simply ensures that the following command should be run by the
&lt;tt class="docutils literal"&gt;mysite&lt;/tt&gt; user instead of root.&lt;/p&gt;
&lt;p&gt;The script has to be executable for daemontools to recognize it, so let's make
sure it is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo chmod +x /etc/service/mysite/run
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can verify that it's running by using the &lt;tt class="docutils literal"&gt;svstat&lt;/tt&gt; command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo svstat /etc/service/mysite/
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The results should look something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;/etc/service/mysite/: up &lt;span class="o"&gt;(&lt;/span&gt;pid 3610&lt;span class="o"&gt;)&lt;/span&gt; 33 seconds
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That means that the process is up, it's got a process identifier of 3610, and
it's been up for 33 seconds.  You can use the &lt;tt class="docutils literal"&gt;svc&lt;/tt&gt; command to take the
service down like so:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo svc -d /etc/service/mysite/
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then, if you run &lt;tt class="docutils literal"&gt;svstat&lt;/tt&gt; on it again, you should get this output:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;/etc/service/mysite/: down 4 seconds, normally up
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To bring it back up, simply run this command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo svc -u /etc/service/mysite/
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A full list of &lt;tt class="docutils literal"&gt;svc&lt;/tt&gt; commands can be found on &lt;a class="reference external" href="http://cr.yp.to/daemontools/svc.html"&gt;online&lt;/a&gt;, and is essential
reading if you're going to dive deeper into daemontools.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="configuring-nginx-to-talk-to-our-server"&gt;
&lt;h1&gt;Configuring Nginx to Talk to our Server&lt;/h1&gt;
&lt;p&gt;We're nearing the finish line, all we have left to do is configure nginx to
talk to our FastCGI server to get its HTTP responses and serve those to the
user.&lt;/p&gt;
&lt;p&gt;Ubuntu comes with a helpful file at &lt;tt class="docutils literal"&gt;/etc/nginx/fastcgi_params&lt;/tt&gt;,
unfortunately it's not quite right.  It encodes a parameter named
&lt;tt class="docutils literal"&gt;SCRIPT_NAME&lt;/tt&gt;, but what our server really wants is &lt;tt class="docutils literal"&gt;PATH_INFO&lt;/tt&gt;.  You can
either do a search and replace, or copy the contents below into the
&lt;tt class="docutils literal"&gt;/etc/nginx/fastcgi_params&lt;/tt&gt; file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;fastcgi_param  QUERY_STRING       &lt;span class="nv"&gt;$query_string&lt;/span&gt;;
fastcgi_param  REQUEST_METHOD     &lt;span class="nv"&gt;$request_method&lt;/span&gt;;
fastcgi_param  CONTENT_TYPE       &lt;span class="nv"&gt;$content_type&lt;/span&gt;;
fastcgi_param  CONTENT_LENGTH     &lt;span class="nv"&gt;$content_length&lt;/span&gt;;

fastcgi_param  PATH_INFO          &lt;span class="nv"&gt;$fastcgi_script_name&lt;/span&gt;;
fastcgi_param  REQUEST_URI        &lt;span class="nv"&gt;$request_uri&lt;/span&gt;;
fastcgi_param  DOCUMENT_URI       &lt;span class="nv"&gt;$document_uri&lt;/span&gt;;
fastcgi_param  DOCUMENT_ROOT      &lt;span class="nv"&gt;$document_root&lt;/span&gt;;
fastcgi_param  SERVER_PROTOCOL    &lt;span class="nv"&gt;$server_protocol&lt;/span&gt;;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/&lt;span class="nv"&gt;$nginx_version&lt;/span&gt;;

fastcgi_param  REMOTE_ADDR        &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;;
fastcgi_param  REMOTE_PORT        &lt;span class="nv"&gt;$remote_port&lt;/span&gt;;
fastcgi_param  SERVER_ADDR        &lt;span class="nv"&gt;$server_addr&lt;/span&gt;;
fastcgi_param  SERVER_PORT        &lt;span class="nv"&gt;$server_port&lt;/span&gt;;
fastcgi_param  SERVER_NAME        &lt;span class="nv"&gt;$server_name&lt;/span&gt;;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we're going to create the definition for our site, let's use our editor and
create the file &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/etc/nginx/sites-available/mysite&lt;/span&gt;&lt;/tt&gt; with the following
contents:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;mysite.com&lt;/span&gt; &lt;span class="s"&gt;www.mysite.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;access_log&lt;/span&gt; &lt;span class="s"&gt;/var/log/nginx/mysite.access.log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/media&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;autoindex&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="s"&gt;/home/mysite/mysite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="s"&gt;/etc/nginx/fastcgi_params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;fastcgi_pass&lt;/span&gt; &lt;span class="n"&gt;127.0.0.1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This says to listen on port 80 (the standard for HTTP) for &lt;em&gt;http://mysite.com/&lt;/em&gt;
and &lt;em&gt;http://www.mysite.com/&lt;/em&gt;.  It says that requests for /media should be served
directly from disk from the &lt;tt class="docutils literal"&gt;/home/mysite/mysite/media&lt;/tt&gt; directory.  And most
importantly, it says that anything else should be passed via FastCGI to our
server.&lt;/p&gt;
&lt;p&gt;Now let's hook this up via symlink:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo ln -s /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/mysite
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And finally we can restart nginx to have the new settings take effect:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo /etc/init.d/nginx restart
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusions"&gt;
&lt;h1&gt;Conclusions&lt;/h1&gt;
&lt;p&gt;We have now set up a very minimal server, using nginx to serve media at blazing
fast speeds, and a pure-python FastCGI server to serve dynamic requests.  Nginx
speaks directly to the FastCGI server without any layers in-between.  Using
daemontools, we have complete control over that FastCGI process, and we can
stop it, restart it, or change its settings at any time.&lt;/p&gt;
&lt;p&gt;The really interesting thing is that with just a few small tweaks, this exact
same stack could be used for a &lt;a class="reference external" href="http://github.com/benoitc/gunicorn"&gt;gunicorn&lt;/a&gt;, &lt;a class="reference external" href="http://pypi.python.org/pypi/Spawning"&gt;spawning&lt;/a&gt;, or &lt;a class="reference external" href="http://pythonpaste.org/modules/httpserver"&gt;paste&lt;/a&gt; solution.
Instead of doing &lt;tt class="docutils literal"&gt;fastcgi_pass&lt;/tt&gt;, we would simply use &lt;tt class="docutils literal"&gt;proxy_pass&lt;/tt&gt;.  We'd
still use daemontools to keep the process running and control it.  Almost every
single other step of this article would apply.&lt;/p&gt;
&lt;p&gt;This is a very viable alternative to the oft-touted stack of Apache/mod_wsgi
and hopefully after reading this article, more people will consider it as a
deployment method.&lt;/p&gt;
&lt;/div&gt;
</summary></entry><entry><title>History of Model Validation</title><link href="http://djangoadvent.com/1.2/history-model-validation/" rel="alternate" /><updated>2010-02-18T00:00:00-11:00</updated><author><name>Honza Král</name><uri>http://djangopeople.net/king/</uri></author><id>http://djangoadvent.com/1.2/history-model-validation/</id><summary type="html">&lt;div class="section" id="motivation"&gt;
&lt;h1&gt;Motivation&lt;/h1&gt;
&lt;p&gt;When working with Django's awesome (new)forms framework I always felt a slight
pang of pain that something similarly awesome isn't available for Django's
model layer.&lt;/p&gt;
&lt;p&gt;Sure, you can create a ModelForm which is very cool and usually good enough
when you are only dealing with user input, especially after newforms admin
landed and enabled people to supply their own form class. But if you are not
dealing with users, don't have a single origin of your model or are dealing
with other developers instead, things can get out of hand pretty quickly. If,
on the other hand, you could define your validation in one place and have it
propagated to all necessary places (ModelForm, admin), that's where you can
really be sure that you have done enough to keep your data in a consistent
state.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="first-draft"&gt;
&lt;h1&gt;First draft&lt;/h1&gt;
&lt;p&gt;I first started working on model-validation during PyCON in 2008. It was my
first python conference and first time meeting other Djangonauts that I
previously only communicated with over email. It was a very stimulating
atmosphere which inspired me to try and tackle this problem.&lt;/p&gt;
&lt;p&gt;At the end of the sprint I had an &lt;em&gt;almost working&lt;/em&gt; prototype of model
validation. Very naive and missing most of the features it has in 1.2 or even
some that ModelForms have in 1.1 (for example &lt;tt class="docutils literal"&gt;validate_unique&lt;/tt&gt;). I continued
working on it throughout the year, especially during conferences. Right before
1.0 was out of the door I even got into a discussion with some core devs about
how we can merge it. Unfortunately for me, but not for Django, newforms-admin
was ready earlier and had a higher priority. After newforms-admin landed, my
patch lied in ruins &amp;#8212; it was easier to rewrite it from scratch then to try and
apply the model-validation merge.&lt;/p&gt;
&lt;p&gt;The came another conference (Djangocon 2008) where I got two legendary core
developers to sit down and spare a few minutes discussing what model-validation
should look like, especially focusing on validators. I tried to incorporate
their ideas and failed horribly, ending up with another &lt;em&gt;almost working&lt;/em&gt; patch
in desperate need of some attention. Fortunately&lt;a class="footnote-reference" href="#id2" id="id1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; during yet another
conference I got to talking with yet another great Djangonaut of German origin
who inspired me to apply for the GSOC program. After I answered all the &amp;quot;How
come you are still a student?&amp;quot; questions, I got accepted and thus ran out of
excuses why I never finished the patch and became the champion of &lt;em&gt;almost
working&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="gsoc"&gt;
&lt;h1&gt;GSOC&lt;/h1&gt;
&lt;p&gt;&lt;a class="reference external" href="http://code.google.com/soc/"&gt;Google Summer of Code&lt;/a&gt; is a great program by Google to encourage students to
work on open source projects. Since I was (and still am) a student, managed to
write a feature proposal before the deadline (with full four hours to spare)
and showed that I am stubborn enough to potentially finish it, I got accepted
with Joseph Kocherhans as my mentor. I spent the summer working on the patch,
moving a lot of code around &amp;#8212; from formfields to validators and modelfields,
from modelforms to models and, finally, from old patch to new &lt;a class="reference external" href="http://code.djangoproject.com/browser/django/branches/soc2009/model-validation"&gt;SVN branch&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At the end of the summer I got, what I thought was, a clean implementation of
model validation. However, as I thought about it &amp;#8212; it was very hard to create
a model that would pass the validation and then fail to save itself into the
database.  In my eagerness to finish the patch and provide a clean solution I
forgot one &lt;em&gt;minor&lt;/em&gt; detail &amp;#8212; people don't work with clean models, most of the
time, when manipulating a model instance, you work with a partial model, often
constructed by a ModelField with fields excluded.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="back-to-reality"&gt;
&lt;h1&gt;Back to reality&lt;/h1&gt;
&lt;p&gt;It became apparent when Joseph merged the branch into trunk that this oversight
on my part is something that will upset many people and, as such, is not
acceptable to be a part of the next release. After a brief panic attack we dove
into the code rethinking our approach to the patch, especially regarding
&lt;tt class="docutils literal"&gt;ModelForms&lt;/tt&gt;.  Where our priority originally was to create a bullet-proof
system that would make it very hard for people to corrupt their models, our new
priority became to keep everything as before the merge and provide a clear
migration path for people wanting to do more validation.&lt;/p&gt;
&lt;p&gt;So, essentially after the fourth rethinking of our approach, we arrived at the
API you see today in trunk, which you can read about in the &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/ref/validators/#ref-validators"&gt;Validators&lt;/a&gt; and
the &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/ref/models/instances/#validating-objects"&gt;Validating Objects&lt;/a&gt; documentation.&lt;/p&gt;
&lt;table class="docutils footnote" frame="void" id="id2" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;I would like to think that this was fortunate for both Django and myself.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</summary></entry><entry><title>Django Template Improvements</title><link href="http://djangoadvent.com/1.2/django-template-improvements/" rel="alternate" /><updated>2010-02-17T00:00:00-11:00</updated><author><name>Alex Gaynor</name><uri>http://alexgaynor.net/</uri></author><id>http://djangoadvent.com/1.2/django-template-improvements/</id><summary type="html">&lt;div class="section" id="init"&gt;
&lt;h1&gt;__init__&lt;/h1&gt;
&lt;p&gt;Almost every request to your Django site renders a template.  Django handles
these pretty snapilly &amp;#8212; after all it's not so expensive to load the template
file and compile it before rendering it each request.  But what happens if your
site renders hundreds of templates per request?  If you're rendering 500
templates per request, even if they only take one millisecond each you've added
half a second of overhead to each request.  It turns out this is exactly the
problem the developers at TypePad encountered when developing their Motion
software.  The result of this was a set of improvements to the templating
system to allow for caching of compiled template objects, however this set of
improvements also makes the template loader system more flexible in a few other
ways.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="caching"&gt;
&lt;h1&gt;Caching&lt;/h1&gt;
&lt;p&gt;The most obvious improvement &lt;a class="reference external" href="http://code.djangoproject.com/changeset/11862"&gt;changeset 11862&lt;/a&gt; brings is the inclusion of a
new cached template loader.  This loader is instantiated with a list of other
template loaders, and then it loads templates using those loaders, but caching
the compiled template objects.  This is helpful because, previously, the
template was reparsed and compiled on each render.  If you were rendering a lot
of templates on each request (such as including another template inside of a
loop) this could incur a lot of overhead.&lt;/p&gt;
&lt;p&gt;If you want to update your site to take advantage of this loader it's just a
matter of changing your settings to use this new loader.  The cached template
loader is a class-based loader that you configure with a list of other loaders
that it should wrap. The wrapped loaders are used to locate unknown templates
when they are first encountered.  The cached loader then stores the compiled
&lt;tt class="docutils literal"&gt;Template&lt;/tt&gt; in memory. The cached &lt;tt class="docutils literal"&gt;Template&lt;/tt&gt; instance is returned for
subsequent requests to load the same template.&lt;/p&gt;
&lt;p&gt;For example, to enable template caching with the &lt;tt class="docutils literal"&gt;filesystem&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;app_directories&lt;/tt&gt; template loaders you might use the following settings:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;TEMPLATE_LOADERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;django.template.loaders.cached.Loader&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;&amp;#39;django.template.loaders.filesystem.Loader&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;&amp;#39;django.template.loaders.app_directories.Loader&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="caveats"&gt;
&lt;h1&gt;Caveats&lt;/h1&gt;
&lt;p&gt;Most environments that Django is deployed in use multiple threads to serve
Django requests.  This presented one of the major challenges to supporting
cached templates in Django.  This is because a cached template means it could
be used used from multiple threads simultaneously.  Before this patch landed,
Django template objects were not thread safe, rendering the same template
object from multiple threads could produce incorrect results.  However, with
this patch, Django's template objects became threadsafe, including all of the
builtin template tags (specifically &lt;tt class="docutils literal"&gt;{% block %}&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;{% cycle %}&lt;/tt&gt;).&lt;/p&gt;
&lt;p&gt;Before it is safe to use the cached template loader with your own applications
you need to make sure that all of your custom template tags are threadsafe.
Fortunately the Django documentation provides an excellent guide on &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#thread-safety-considerations"&gt;thread
safety considerations&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="bonus"&gt;
&lt;h1&gt;Bonus&lt;/h1&gt;
&lt;p&gt;Previously, template loaders were required to return the string of the
template, rather than the template object.  This was another problem the
aforementioned patch solved.  This was a problem because the entire point of a
cached template loader is that it returns a precompiled template object.
Therefore this patch allows template loaders to return template objects&lt;a class="footnote-reference" href="#id2" id="id1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;.
However, this also allows one to build a template loader that works with other
template languages (such as Jinja, Cheeta, Mako, or any other language that
works by taking a string and a dictionary).  Before if you wanted to use
another template language with Django you either had to monkey patch Django
extensively, or replace every call to something like &lt;tt class="docutils literal"&gt;render_to_response()&lt;/tt&gt;
with your own function that used your alternate template language.  Now, in
Django 1.2, all you need to do is write a template loader with a
&lt;tt class="docutils literal"&gt;load_template()&lt;/tt&gt; method that returns a template object.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;This patch provides several important improvements to Django's templating
systems' performance and flexibility.  As always the documentation is an
excellent resource when it comes to taking advantage of these features of the
templating system.&lt;/p&gt;
&lt;table class="docutils footnote" frame="void" id="id2" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Defined as something with a &lt;tt class="docutils literal"&gt;render()&lt;/tt&gt; method.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</summary></entry><entry><title>Natural Keys</title><link href="http://djangoadvent.com/1.2/natural-keys/" rel="alternate" /><updated>2010-02-16T00:00:00-11:00</updated><author><name>Russell Keith-Magee</name><uri>http://cecinestpasun.com/</uri></author><id>http://djangoadvent.com/1.2/natural-keys/</id><summary type="html">&lt;p&gt;One of the features introduced in Django 1.2 is really little more
than a fix for a long standing bug. Natural Keys were introduced as a
way to solve a very specific problem with fixture loading.&lt;/p&gt;
&lt;p&gt;However, there's a little bit more to this feature than a simple
bugfix. If you look outside the box, Natural Keys are a handy utility
for simplifying the way you access certain types of models.&lt;/p&gt;
&lt;p&gt;In order to understand when natural keys are useful, it helps to know
little history.&lt;/p&gt;
&lt;div class="section" id="in-the-beginning"&gt;
&lt;h1&gt;In the beginning ...&lt;/h1&gt;
&lt;p&gt;When Django's test framework was first introduced, it didn't include any
support for fixtures. If you wanted a test case to have data, you used
the ORM to define those data in the &lt;tt class="docutils literal"&gt;setUp()&lt;/tt&gt; method of each
&lt;tt class="docutils literal"&gt;TestCase&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;This worked, but it wasn't especially easy to use. Writing large
collections of test data was needlessly complex. There was no way to
create test data using a running Django project, and then dump that
data in a way that test framework could use it. Reusing test data
between test cases required the creation of libraries of code that set
up certain test objects.&lt;/p&gt;
&lt;p&gt;So - a really simple test case might look something like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.test&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;library.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;library.utils&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;is_good_book&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setUp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Douglas&amp;#39;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Douglas&amp;#39;&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Mostly Harmless&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a1&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_stuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_good_book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Functional? Yes. Pretty? Not especially.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="let-there-be-fixtures"&gt;
&lt;h1&gt;Let there be fixtures!&lt;/h1&gt;
&lt;p&gt;Fixture support for Django tests arrived in January 2007. There wasn't anything
especially revolutionary about Django's test fixtures &amp;#8212; Django's serialization
framework had been part of Django for a while.  Test fixtures just leveraged
that serialization support in a new and interesting way.&lt;/p&gt;
&lt;p&gt;With the introduction of fixtures, you could put all the data definition into a
separate file, in a format that was suited to data definition &amp;#8212; JSON, XML,
YAML, or any other format for which a serializer existed.  As a result, the
test code becomes a lot clearer:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.test&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;library.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;library.utils&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;is_good_book&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;fixtures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;test_library.json&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_stuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;b1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Mostly Harmless&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_good_book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The data for the test is then defined in a separate test fixture file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;model&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;library.author&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;fields&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;first_name&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Douglas&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;last_name&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Adams&amp;quot;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;model&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;library.book&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;fields&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Mostly Harmless&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;author&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This test fixture can be reused between tests without the need to
create test data libraries. The production of test fixtures can also
be semi-automated &amp;#8212; if you have a running project, you can use that
project to produce test data, and then use the &lt;tt class="docutils literal"&gt;dumpdata&lt;/tt&gt; management
command to produce test data that can be used as a test fixture.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="houston-we-have-a-problem"&gt;
&lt;h1&gt;Houston, we have a problem&lt;/h1&gt;
&lt;p&gt;The test fixture format is an improvement over programmatic definition
of test data, but it isn't without flaws. For example, the test
fixture uses primary keys to reference other objects &amp;#8212; you define the
author of a book by specifying &lt;tt class="docutils literal"&gt;&amp;quot;author&amp;quot; : 1&lt;/tt&gt; in your fixture.&lt;/p&gt;
&lt;p&gt;This isn't an especially natural way of referencing objects &amp;#8212; but,
test fixture production can be automated, so unless you are manually
writing fixtures, this inconvenience doesn't really affect you.&lt;/p&gt;
&lt;p&gt;However, the problem is slightly more than an inconvenience for
certain types of data.&lt;/p&gt;
&lt;div class="section" id="the-post-syncdb-handler"&gt;
&lt;h2&gt;The post_syncdb handler&lt;/h2&gt;
&lt;p&gt;Django provides a lot of runtime metadata about the objects under it's
control. The contrib.ContentTypes app provides a unique identifier for
every data type that is registered as a Django object. The
contrib.Auth app automatically creates access permissions for every
model that is defined. All this meta data is stored in normal Django
models; these models are populated using a &lt;tt class="docutils literal"&gt;post_syncdb&lt;/tt&gt; handler.&lt;/p&gt;
&lt;p&gt;Whenever you run &lt;tt class="docutils literal"&gt;./manage.py syncdb&lt;/tt&gt;, Django emits a
&lt;tt class="docutils literal"&gt;post_syncdb&lt;/tt&gt; signal. By registering a listener for this signal, it
is possible for your application to to execute code in response to a
&lt;tt class="docutils literal"&gt;syncdb&lt;/tt&gt;. In the case of contenttypes, this means creating a new
content type entry; in the case of the auth framework, it means
creating permissions.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="so-what-s-the-problem"&gt;
&lt;h2&gt;So what's the problem?&lt;/h2&gt;
&lt;p&gt;The consequence of this signal-listening is that new objects will be
produced in the database as the result of a call to &lt;tt class="docutils literal"&gt;syncdb&lt;/tt&gt;. The
handler is told the names of the new models that have been created,
and creates content types, permissions, and other database objects to
reflect those additions.&lt;/p&gt;
&lt;p&gt;But what are the primary keys of these new objects?&lt;/p&gt;
&lt;p&gt;The primary keys that are allocated are determined at runtime, and
can't be predicted. The keys allocated during normal execution aren't
necessarily the primary keys that will be allocated on a test database
during test execution. The keys allocated on my database won't
necessarily match those allocated on your database.&lt;/p&gt;
&lt;p&gt;So, if you have a model that references content types &amp;#8212; for example,
if you have an object that uses generic foreign keys &amp;#8212; then you can't
create a fixture that will consistently reproduce that object. There is
literally no primary key value you can use that will be guaranteed to
uniquely identify a content type (or any other dynamically created
data object for that matter).&lt;/p&gt;
&lt;p&gt;This problem was the nub of &lt;a class="reference external" href="http://code.djangoproject.com/ticket/7052"&gt;ticket #7052&lt;/a&gt;. It wasn't just a problem for
content types and permissions, either &amp;#8212; although these two models in
particular were the most frequently reported manifestations of the
problem. Any model that had dynamically defined data would be prone to
the same issues.&lt;/p&gt;
&lt;p&gt;Ironically, this problem didn't actually exist in the pre-fixture
world. When you programatically define a fixture, you aren't limited
to using primary keys to reference objects (although you could if you
wanted to). You could use any attribute or combination of attributes
that uniquely reference an object.&lt;/p&gt;
&lt;p&gt;What we really need is a way to programmatically look up a dynamic
content type in a fixture instead of hard coding a primary key value.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="natural-keys-to-the-rescue"&gt;
&lt;h1&gt;Natural Keys to the rescue!&lt;/h1&gt;
&lt;p&gt;This is what natural keys are for. Instead of using primary key
values to reference an object, you can use a natural key. So, if your
fixture previously had a primary key reference for a content type:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="s2"&gt;&amp;quot;content_type&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;37&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;... you can replace that primary key value with a natural key:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="s2"&gt;&amp;quot;content_type&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;library&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;book&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The natural key itself is just a list of data values that can be used
to uniquely identify an object in the database. In the case of a
content type, the natural key is composed out of the &lt;tt class="docutils literal"&gt;app_label&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;model&lt;/tt&gt; that forms the content type record.&lt;/p&gt;
&lt;p&gt;This natural key will be resolved into a primary key value when the
fixture is loaded. The content type model itself provides the method
that defines how to resolve the natural key reference into an actual
database object.&lt;/p&gt;
&lt;div class="section" id="defining-a-natural-key"&gt;
&lt;h2&gt;Defining a natural key&lt;/h2&gt;
&lt;p&gt;So, how do you declare that your model can be loaded using natural
keys? Easy &amp;#8212; you define a &lt;tt class="docutils literal"&gt;get_by_natural_key()&lt;/tt&gt; method on the
default manager for the model. This &lt;tt class="docutils literal"&gt;get_by_natural_key()&lt;/tt&gt; method
accepts a list of arguments; those arguments are the elements of the
list that are defined in the fixture. In the case of content types,
the &lt;tt class="docutils literal"&gt;get_by_natural_key()&lt;/tt&gt; method looks something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ContentTypeManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Manager&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_by_natural_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;app_label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;app_label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That's all there is to it. The &lt;tt class="docutils literal"&gt;get_by_natural_key()&lt;/tt&gt; method is just
a method that does a specific model lookup, provided under a known
name so the serializers know how to find it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="producing-a-natural-key"&gt;
&lt;h2&gt;Producing a natural key&lt;/h2&gt;
&lt;p&gt;Well... there is a little more. If all you want to do is load natural
keys, then all you need is the &lt;tt class="docutils literal"&gt;get_by_natural_key()&lt;/tt&gt; method.
However, if you're going to use &lt;tt class="docutils literal"&gt;dumpdata&lt;/tt&gt; to produce fixtures, it
would be nice to have those fixtures produced with natural keys in
place of primary key references.&lt;/p&gt;
&lt;p&gt;To close the loop, you need to define one more method, this time on the
model itself. If your model defines a &lt;tt class="docutils literal"&gt;natural_key()&lt;/tt&gt; method, Django
knows that references to objects of this type can be output as natural
key references. The &lt;tt class="docutils literal"&gt;natural_key()&lt;/tt&gt; method accepts no arguments; it
returns the list of values that can be used to uniquely identify the object.&lt;/p&gt;
&lt;p&gt;For content types, the definition of &lt;tt class="docutils literal"&gt;natural_key()&lt;/tt&gt; looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ContentType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c"&gt;# ...&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;natural_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;app_label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By default, Django doesn't use natural keys when it dumps fixtures. If
you want a fixture to use natural keys, you must specify the
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--natural&lt;/span&gt;&lt;/tt&gt; option when you call &lt;tt class="docutils literal"&gt;dumpdata&lt;/tt&gt; (or the
&lt;tt class="docutils literal"&gt;use_natural_keys=True&lt;/tt&gt; argument if you are programatically calling
the serializers).&lt;/p&gt;
&lt;p&gt;For example, the following would dump all the objects
defined in the library application in JSON format, using 2 character
indents, using natural keys whenever they are available:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;./manage.py dumpdata --format&lt;span class="o"&gt;=&lt;/span&gt;json --indent&lt;span class="o"&gt;=&lt;/span&gt;2 --natural library
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="some-caveats-and-suggestions"&gt;
&lt;h2&gt;Some caveats and suggestions&lt;/h2&gt;
&lt;p&gt;Any object can define a natural key by providing the
&lt;tt class="docutils literal"&gt;get_by_natural_key()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;natural_key()&lt;/tt&gt; methods. However,
that natural key must be composed out of one or more attributes that
are guaranteed to be unique in the database.&lt;/p&gt;
&lt;p&gt;The easiest way to ensure this uniqueness is to define attributes to
be &lt;tt class="docutils literal"&gt;unique_together&lt;/tt&gt; in the &lt;tt class="docutils literal"&gt;Meta&lt;/tt&gt; options of the model. This
enforces uniqueness at the database level; it also adds an index to
the database which will speed up the retrieval of objects by natural
key.&lt;/p&gt;
&lt;p&gt;Uniqueness doesn't need to be enforced at the database level, but the
attributes you use in a natural key must be unique in practice. If you
choose not to define the attributes as &lt;tt class="docutils literal"&gt;unique_together&lt;/tt&gt;, you might
find it beneficial to add indexes to the individual columns (or define a
multi-column index). This will speed up the natural key lookups.&lt;/p&gt;
&lt;p&gt;When using natural keys in a fixture, you need to be careful of the
order in which you define fixture objects. Natural keys are resolved
by performing a lookup on the database &amp;#8212; which means you can't
reference a natural key in a fixture before the object it references
has been defined.&lt;/p&gt;
&lt;p&gt;This means that the object that is referenced must already exist in
the database before you load the fixture. If you call &lt;tt class="docutils literal"&gt;dumpdata&lt;/tt&gt;,
Django will dump objects in an order that contains no ambiguity.
However, if you're manually defining fixtures, you need to be careful
to ensure that the object order contains no forward natural key
references.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="back-to-the-books"&gt;
&lt;h1&gt;Back to the books...&lt;/h1&gt;
&lt;p&gt;So, natural keys can be used to avoid a specific problem with test
fixtures. Is that all they are good for? In short &amp;#8212; no.&lt;/p&gt;
&lt;p&gt;What is a natural key really? A natural key is a composite database
key that can be used to refer to a specific object in a database.
Although dynamic lookups in a fixture are one use for a natural key,
they can also be used in day-to-day code, whenever you need to refer
to an object in a 'natural' way.&lt;/p&gt;
&lt;p&gt;Returning to our Author example &amp;#8212; an obvious natural key for an
author is the first name and last name of the author. By adding the
two natural key methods to our Author model:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthorManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Manager&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_by_natural_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;objects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AuthorManager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;last_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__unicode__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;u&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;natural_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;...the lookup of an author:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Douglas&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Adams&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;...can be replaced with a natural key lookup:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_by_natural_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Douglas&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Adams&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="errr-so-what"&gt;
&lt;h2&gt;Errr... So what?&lt;/h2&gt;
&lt;p&gt;Ok &amp;#8212; a 6 character gain isn't really a big advantage. The elegance of
using a natural key for object lookup only becomes apparent when you
have a more complex natural key.&lt;/p&gt;
&lt;p&gt;Consider the case of Permissions. The natural key for a permission is
composed out of the code name for the permission, and the natural key
for the content type that the permission relates to. So, the following
permission lookup:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;Permission&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;add&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ContentType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;library&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;book&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;...can be replaced by the much more elegant call:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;Permission&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_by_natural_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;add&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;library&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;book&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Taking this a step further, natural keys don't need to map directly
onto database attributes at all. Natural keys can be composed out of
any unique value that can be converted into a unique query for an
object instance. So - if you can pass in a value (or list of values),
and parse those values in some meaningful way into a unique object
lookup, you can use those values as a natural key.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Natural keys may not be as complex as multiple database support or
model validation, but it is a really important improvement introduced
by Django 1.2. The bug that is fixed by introducing natural keys is a
long standing problem that has caused more than one headache. There
are also benefits to be had outside of the test framework.&lt;/p&gt;
&lt;p&gt;So - time to upgrade and enjoy your natural keys!&lt;/p&gt;
&lt;/div&gt;
</summary></entry><entry><title>Object Permissions</title><link href="http://djangoadvent.com/1.2/object-permissions/" rel="alternate" /><updated>2010-02-15T00:00:00-11:00</updated><author><name>Florian Apolloner</name><uri>http://djangopeople.net/apollo13/</uri></author><id>http://djangoadvent.com/1.2/object-permissions/</id><summary type="html">&lt;div class="section" id="introduction"&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Nearly every web application provides authorization support to limit access to
certain pages to a privileged group of users. Since the patterns for permission
checks are usually the same for every application, it makes sense for Django to
provide an API for it. Even better, Django does it in a clever way, so
developers can use this API in their applications and, if they like, write
backends for the API itself. This way end-users can switch those backends to
perform permission checks against other databases or servers, simply by
choosing another backend in the settings file.&lt;/p&gt;
&lt;p&gt;Django has had support for authentication backends for quite some time. In
Django 1.0 support for authorization backends got added in &lt;a class="reference external" href="http://code.djangoproject.com/changeset/6375"&gt;r6375&lt;/a&gt;. The code
which previously checked the permission tables was moved from the user model
into the &lt;tt class="docutils literal"&gt;ModelBackend&lt;/tt&gt; and the user objects delegated their checks to the
backend.  Django 1.2 adds object permission checks to the existing backends
in &lt;a class="reference external" href="http://code.djangoproject.com/changeset/11807"&gt;r11807&lt;/a&gt;.  For now it is really just a foundation &amp;#8212; the default backend
does not support it, nor does the admin application take advantage of object
permissions.  Nevertheless we can easily enhance the admin application to
perform the necessary checks and write our own backend.&lt;/p&gt;
&lt;p&gt;Before we start writing our own backend it is important to know which
possibilities do exist. Django supports multiple authentication/authorization
backends at the same time, which allows us to implement the stuff we want
to support and pass the remaining parts (eg. authentication) to default
backends like &lt;tt class="docutils literal"&gt;ModelBackend&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;RemoteUserBackend&lt;/tt&gt;. There are many ways
to write such a backend &amp;#8212; we could use a LDAP server and query it for
permissions or use the database of another application (like Drupal, phpBB,
etc.) &amp;#8212; but to keep this article short and readable we will use a simple Model
and store the data in our own database.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="writing-an-object-aware-authorization-backend"&gt;
&lt;h1&gt;Writing an object aware authorization backend&lt;/h1&gt;
&lt;div class="section" id="let-s-start-simple"&gt;
&lt;h2&gt;Let's start simple&lt;/h2&gt;
&lt;p&gt;Django installs three default permissions for every model: &lt;tt class="docutils literal"&gt;add&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;change&lt;/tt&gt;
and &lt;tt class="docutils literal"&gt;delete&lt;/tt&gt;. In our case only the &lt;tt class="docutils literal"&gt;change&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;delete&lt;/tt&gt; permissions make
sense, as the &lt;tt class="docutils literal"&gt;add&lt;/tt&gt; permission is not related to an object but the model.
Instead we will add a &lt;tt class="docutils literal"&gt;view&lt;/tt&gt; permission. We will use the content types
framework to allow greater reuse-ability. Enough of the talking,  start with
the model:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.contrib.auth.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.contrib.contenttypes&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nn"&gt;models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ContentType&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectPermission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;can_view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BooleanField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;can_change&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BooleanField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;can_delete&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BooleanField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;content_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ContentType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;object_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PositiveIntegerField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There should be nothing new about this model, &lt;tt class="docutils literal"&gt;__unicode__&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Meta&lt;/tt&gt; and
translations are left out for the sake of simplicity. As we used generic
relations we will be able to display this model as inlines in the admin
application everywhere we want permission checks. Before we start writing the
actual admin integration, here is the code for the backend:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.conf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.contrib.contenttypes.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ContentType&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.contrib.auth.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;objperms.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ObjectPermission&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectPermBackend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;supports_object_permissions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="n"&gt;supports_anonymous_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;has_perm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;perm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;user_obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_authenticated&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;user_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ANONYMOUS_USER_ID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

        &lt;span class="n"&gt;ct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ContentType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_for_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;perm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;perm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;_&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;IndexError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

        &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ObjectPermission&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                            &lt;span class="n"&gt;object_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                            &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;can_&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;perm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now what is new in this snippet? Compared to Django versions before 1.2 we
added an &lt;tt class="docutils literal"&gt;obj&lt;/tt&gt; parameter to the &lt;tt class="docutils literal"&gt;has_perm&lt;/tt&gt; method and set the
&lt;tt class="docutils literal"&gt;supports_*&lt;/tt&gt; attributes to &lt;tt class="docutils literal"&gt;True&lt;/tt&gt;. The &lt;tt class="docutils literal"&gt;supports_*&lt;/tt&gt; attributes got added
in 1.2 to allow new backends to advertise their capabilities. These attributes
are needed to allow older backends to work unmodified in Django 1.2. As
mentioned in the &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/internals/deprecation/"&gt;deprecation timeline&lt;/a&gt;, in Django 1.4 the attributes will
become redundant and backends have to support &lt;tt class="docutils literal"&gt;obj&lt;/tt&gt; and anonymous users.
Django currently requires &lt;tt class="docutils literal"&gt;authenticate&lt;/tt&gt; to be implemented, so we implement
it and simply return &lt;tt class="docutils literal"&gt;None&lt;/tt&gt; as we don't care about authentication. The only
remaining code is the implementation for the &lt;tt class="docutils literal"&gt;has_perm&lt;/tt&gt; method. What about
other methods? There are none, at least none which we will need to write: As we
don't support authentication we don't need to implement &lt;tt class="docutils literal"&gt;authenticate&lt;/tt&gt; or
&lt;tt class="docutils literal"&gt;get_user&lt;/tt&gt;.  &lt;tt class="docutils literal"&gt;has_module_perms&lt;/tt&gt; does not make sense in our case and does
not support the &lt;tt class="docutils literal"&gt;obj&lt;/tt&gt; parameter either. We could implement
&lt;tt class="docutils literal"&gt;get_all_permissions&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;get_group_permissions&lt;/tt&gt; but we won't gain anything
from it; neither does Django use them internally nor do we need them in this
example. That said, those last two methods are the only two you might want to
implement (in addition to &lt;tt class="docutils literal"&gt;has_perm&lt;/tt&gt;) when writing your own backend. The code
above should be pretty straightforward: We ignore permission checks where the
object is &lt;tt class="docutils literal"&gt;None&lt;/tt&gt; &amp;#8212; &lt;tt class="docutils literal"&gt;ModelBackend&lt;/tt&gt; can take care of them. Then we check if
the user is authenticated and replace the &lt;tt class="docutils literal"&gt;AnonymousUser&lt;/tt&gt; instance with a
real user if he is not authenticated.&lt;a class="footnote-reference" href="#id4" id="id1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; After that we extract the permission
name from the &lt;tt class="docutils literal"&gt;perm&lt;/tt&gt; parameter; this parameter is partially redundant as it
also contains the name of the model and the application, which we don't need
because the &lt;tt class="docutils literal"&gt;obj&lt;/tt&gt; provides the same info already. But the Django admin
application will pass such names in and therefore we will stick to this
convention.&lt;a class="footnote-reference" href="#id5" id="id2"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; One important detail about this backend is that we don't
inherit from &lt;tt class="docutils literal"&gt;ModelBackend&lt;/tt&gt;, which means we will break Django if we use our
backend as the only one, but luckily we can pass a list of backends to
&lt;tt class="docutils literal"&gt;AUTHENTICATION_BACKENDS&lt;/tt&gt; in &lt;tt class="docutils literal"&gt;settings.py&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;AUTHENTICATION_BACKENDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;django.contrib.auth.backends.ModelBackend&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;objperms.backend.ObjectPermBackend&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, as the needed code is in place, it is a good time to test it:&lt;a class="footnote-reference" href="#id6" id="id3"&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FlatPage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;ct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ContentType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_for_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;apo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# Don&amp;#39;t use a superuser here!&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;ObjectPermission&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;can_view&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;                                &lt;span class="n"&gt;can_change&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;can_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;                                &lt;span class="n"&gt;content_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;object_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;&amp;lt;ObjectPermission: &amp;gt;&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_perm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;flatpages.delete_flatpage&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;False&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_perm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;flatpages.view_flatpage&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;True&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="c"&gt;# As mentioned above we could also use:&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_perm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;view&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Apparently everything is working fine.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="wrapping-the-admin-application"&gt;
&lt;h2&gt;Wrapping the admin application&lt;/h2&gt;
&lt;p&gt;Now that the backend is working it is time to take a look at the admin
application. Luckily there are only 2 methods to provide:
&lt;tt class="docutils literal"&gt;has_change_permission&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;has_delete_permission&lt;/tt&gt;, so we will write a
simple mix-in class. If you intend to change more, a subclass of &lt;tt class="docutils literal"&gt;ModelAdmin&lt;/tt&gt;
from which the other admin classes inherit might be more adequate:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.contrib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.contrib.contenttypes.generic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GenericTabularInline&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.contrib.flatpages.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FlatPage&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.contrib.flatpages.admin&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FlatPageAdmin&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;FPAdmin&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;objperms.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ObjectPermission&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectPermissionInline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GenericTabularInline&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ObjectPermission&lt;/span&gt;
    &lt;span class="n"&gt;raw_id_fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;user&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectPermissionMixin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;has_change_permission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_perm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;app_label&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;.&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_change_permission&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;has_delete_permission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_perm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;app_label&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;.&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_delete_permission&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FlatPageAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ObjectPermissionMixin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FPAdmin&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;inlines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FPAdmin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inlines&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ObjectPermissionInline&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unregister&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FlatPage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FlatPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FlatPageAdmin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There is nothing really new in this snippet &amp;#8212; we just override the
&lt;tt class="docutils literal"&gt;has_perm&lt;/tt&gt; checks to include the object and add an inline to the admin, so
the user can assign permissions while adding a new flatpage. The last thing we
are going to fix is the changelist view, which currently lists every object,
even those we don't have access to. We could modify the &lt;tt class="docutils literal"&gt;queryset&lt;/tt&gt; method to
return only the items the user can edit, but this assumes that a database
backend is used and that is not necessarily the case (e.g. LDAP, etc.).
Instead we wrap the change view, catch the &lt;tt class="docutils literal"&gt;PermissionDenied&lt;/tt&gt; error, tell the
user what happened and redirect back to the change list:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# This code goes into ``FlatPageAdmin``&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change_view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FlatPageAdmin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;change_view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;PermissionDenied&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;u&amp;quot;You don&amp;#39;t have the necessary permissions!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;HttpResponseRedirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;admin:flatpages_flatpage_changelist&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above code works fine, but the message gets displayed with a green success
icon, which is not really intuitive. For the sake of simplicity, tweaking the
admin template is left as an exercise for the reader.&lt;/p&gt;
&lt;table class="docutils footnote" frame="void" id="id4" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;You can specify the id of the user you want to represent anonymous users
in your settings file using &lt;tt class="docutils literal"&gt;ANONYMOUS_USER_ID&lt;/tt&gt;.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id5" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Although the code supports a simpler form containing just the permission
name too, but that might break other backends relying on that convention.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id6" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id3"&gt;[3]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;I will use the flatpages application to test them.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
</summary></entry><entry><title>Everything I hate about Mingus</title><link href="http://djangoadvent.com/1.2/everything-i-hate-about-mingus/" rel="alternate" /><updated>2010-02-12T00:00:00-11:00</updated><author><name>Kevin Fricovsky</name><uri>http://blog.montylounge.com/</uri></author><id>http://djangoadvent.com/1.2/everything-i-hate-about-mingus/</id><summary type="html">&lt;div class="section" id="overview"&gt;
&lt;h1&gt;Overview&lt;/h1&gt;
&lt;p&gt;Mingus is a small Django project, created as an experiment in practicing one of
the key features of Django &amp;#8212; reusable apps. Mingus defines no models itself,
but currently leverages 30+ reusable apps to provide one complete blog engine
project.&lt;/p&gt;
&lt;p&gt;This article is about the obstacles faced and lessons learned managing an
application that relies on so many reusable apps, and experiences in
managing a small, open source project.&lt;a class="footnote-reference" href="#id5" id="id1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; It has nothing to do specifically
with all the awesome that exists in Django 1.2.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="what-is-mingus"&gt;
&lt;h1&gt;What is Mingus?&lt;/h1&gt;
&lt;p&gt;Mingus is a blog engine. The act of developing yet another blog engine from
the ground up is a chore really. Mingus exists to do that chore for you. How
nice of Mingus, no?&lt;/p&gt;
&lt;p&gt;So, why is the project a (very) small success? Four key reasons:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;The concept is simple &amp;#8212; a blog engine&lt;/li&gt;
&lt;li&gt;The concept is intriguing &amp;#8212; use only reusable apps to provide all of its
features (blogging, commenting via Disqus, admin image cropping, inlines,
WYSIWYG editor, debugging, contact form, etc.)&lt;/li&gt;
&lt;li&gt;It's a learning tool on how developers can leverage reusable apps in their
project, and a forced introduction to virtualenv and pip.&lt;/li&gt;
&lt;li&gt;It has a minimal, attractive template system.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There is one thing that Mingus really strives to do, and that is to take all of
the combined complexity of 30+ reusable apps, and reduce it into one project
that's brain dead simple to get up and running. Literally, this is what it
takes to get started:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;mkvirtualenv myblog —-no-site-packages
workon myblog
cdvirtualenv
git clone git://github.com/montylounge/django-mingus.git
&lt;span class="nb"&gt;cd &lt;/span&gt;django-mingus/mingus
pip install -r stable-requirements.txt
cp local_settings.py.template local_settings.py
./manage.py syncdb
./manage.py loaddata test_data.json
./manage.py runserver
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For those not familiar, the above commands &lt;cite&gt;mkvirtualenv&lt;/cite&gt;, &lt;cite&gt;workon&lt;/cite&gt;, and
&lt;cite&gt;cdvirtualenv&lt;/cite&gt; requires you have &lt;a class="reference external" href="http://www.doughellmann.com/projects/virtualenvwrapper/"&gt;virtualenvwrapper&lt;/a&gt; installed. I included
the reference to &lt;cite&gt;mkvirtualenv&lt;/cite&gt; and the others as a dependency in the
documentation as a way to introduce developers to the &lt;cite&gt;virtualenvwrapper&lt;/cite&gt;
project if they were not already familiar.&lt;a class="footnote-reference" href="#id6" id="id2"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; I believe it's a terrific tool
that every Python developer should at least be familiar with, and I snuck in
the reference so that maybe it would introduce a new user to the project.
You'll see that tactic used quite often if you take a look throughout the code
base.&lt;/p&gt;
&lt;p&gt;Now we know it's really easy to get started with Mingus, so let's dive in...&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="be-that-guy-or-girl"&gt;
&lt;h1&gt;Be “that guy” (or girl)&lt;/h1&gt;
&lt;p&gt;If you ever started an open source project that gained even a tiny bit of
momentum, then you've received feature requests of varying kinds.
Eventually someone will come along who is using your project but they
need a few extra features that would help him/her along.
Their requests end up in your email inbox and them on your issue
list quite often.&lt;/p&gt;
&lt;p&gt;As a project maintainer, this is where you need to start making some tough
decisions. Are the features requested within the scope of your project's
mission? Do they help make your project more complete? Or are these requests
solely for the benefit of this one individual? Learning when to say &amp;quot;no&amp;quot; to a
request is essential to the successful management of any project. But if the
requests are practical, and if you care, then you are sensitive to things that
should be done correctly and now you've added another action item to add
to your to-do list.&lt;/p&gt;
&lt;p&gt;So you're a good project lead and you fix the bug or add that feature. And if
you really care, while you are refactoring code and you're using your project
daily&lt;a class="footnote-reference" href="#id7" id="id3"&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;, then you start thinking like &amp;quot;that guy&amp;quot; and you start seeing ways
to make your project better. So you spend more time adding new features that
you know are reasonable, and relative to your project's focus. Features that
you may have first overlooked, or simply shrugged off.&lt;/p&gt;
&lt;p&gt;I hate that guy because he adds to my to-do list, but I love that guy because
he's making me a better developer, and he's making my project better. He's my
QA. He's gathering my requirements. Mingus wouldn't be the tiny success that it
is if it wasn't for that guy(s).&lt;/p&gt;
&lt;p&gt;My advice to you — be that guy (or girl) and make me hate you for it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="don-t-make-me-restart-apache"&gt;
&lt;h1&gt;Don't make me restart Apache&lt;/h1&gt;
&lt;p&gt;If there was one feature that I believe the Django admin is missing I would
say application wide settings management.&lt;/p&gt;
&lt;p&gt;The one request I receive on almost every single project I have every been on
is the ability to manage application settings via the admin. I don't care if
it's a Django project or a ASP.Net project &amp;#8212; every single admin user has
needed the ability to manage application wide settings via the admin UI. But
there's no current best practice in managing application wide settings in
Django. We need one, and it needs to be available via the admin.&lt;/p&gt;
&lt;p&gt;Well, actually, there is a best practice out there, but it ends up being a pain
point. The current best practice is to place application settings in the
&lt;cite&gt;settings.py&lt;/cite&gt; file of your project. Here's an example of how to best implement
retrieving that value:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.conf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;span class="n"&gt;post_list_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;post_list_count&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above uses &lt;cite&gt;getattr&lt;/cite&gt; to retrieve the &lt;cite&gt;post_list_count&lt;/cite&gt; value from the
settings instance. If one doesn't exist it defaults to 20. This is terrific and
follows the best practice of &amp;quot;sane defaults&amp;quot;.&lt;/p&gt;
&lt;p&gt;Now, take this example, and lets assume every app in your project (Mingus for
example) requires that one setting is defined per app in your settings.py &amp;#8212; in
Mingus' case you would now have 30 additional values to manage in
&lt;cite&gt;settings.py&lt;/cite&gt;. It's not horrible, but it could lead to an extremely complex
&lt;cite&gt;settings.py&lt;/cite&gt; file when we're all looking to minimize our settings files,
aren't we?&lt;/p&gt;
&lt;p&gt;When following the above convention, if a settings value change is requested,
a developer/sysadmin then needs access to the server to update the
&lt;cite&gt;settings.py&lt;/cite&gt; file themselves. Moreover, whoever handles the change request
also needs to restart the web application server for the change to take affect.
This is less than ideal.&lt;/p&gt;
&lt;p&gt;Lucky for us, two reusable apps attempt to provide that solution:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="http://github.com/sciyoshi/django-dbsettings"&gt;Django-DBSettings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://bitbucket.org/bkroeze/django-livesettings/"&gt;Django-LiveSettings&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I'm not sure which, but one of these solutions (or some of their shared
concepts) should become the convention and ideally an approved contrib
application.&lt;/p&gt;
&lt;p&gt;Sure there are simple settings value:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;BLOG_PAGE_SIZE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And there are more advanced:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;DEBUG_TOOLBAR_PANELS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;debug_toolbar.panels.version.VersionDebugPanel&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;debug_toolbar.panels.timer.TimerDebugPanel&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;debug_toolbar.panels.settings_vars.SettingsVarsDebugPanel&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;debug_toolbar.panels.headers.HeaderDebugPanel&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;debug_toolbar.panels.request_vars.RequestVarsDebugPanel&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;debug_toolbar.panels.template.TemplateDebugPanel&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;debug_toolbar.panels.sql.SQLDebugPanel&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;debug_toolbar.panels.signals.SignalDebugPanel&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;#39;debug_toolbar.panels.logger.LoggingPanel&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The solution? Beyond a simple key/value store each application could provide a
handler. Django would provide default handlers of course...
&lt;cite&gt;IntegerSettingHandler&lt;/cite&gt;, &lt;cite&gt;StringSettingHandler&lt;/cite&gt;, etc. But an application like
&lt;a class="reference external" href="http://robhudson.github.com/django-debug-toolbar/"&gt;django-debug-toolbar&lt;/a&gt; would provide a &lt;cite&gt;DebugToolBarHandler&lt;/cite&gt;. This will allow
the Settings app to have a standard API that any application can interface with
via the Settings API but each custom application provides it's own custom
handler logic to execute its rules on its own. And maybe I'm just crazy?&lt;/p&gt;
&lt;p&gt;There's also the extra query factor for retrieving these values if they exist
in the backend store. So a sensitivity towards performance is required.&lt;/p&gt;
&lt;p&gt;Right now if I want to add an application to Mingus I try to think about the
needs of the non-technical end user. Would they want to be able to change this
setting via the admin? If yes, and the reusable app defines a &lt;cite&gt;settings.py&lt;/cite&gt;
required value, I have a tough decision to make. Do I fork that app and add the
setting to a model which can be updated in the admin&lt;a class="footnote-reference" href="#id8" id="id4"&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt; or do I just fold and
give in, including the app and dropping another value into the project's
&lt;cite&gt;settings.py&lt;/cite&gt;?&lt;/p&gt;
&lt;p&gt;Having a contrib app that resolves these issues would reduce complexity,
maintenance, needless forks of code bases, and improve app flexibility and
integration.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="you-can-get-with-this-setting-or-that-setting"&gt;
&lt;h1&gt;You can get with this Setting or that Setting&lt;/h1&gt;
&lt;p&gt;As if the previous global settings management discussion wasn't exciting
enough, it's now time to talk about managing those settings files.&lt;/p&gt;
&lt;p&gt;In Mingus I package two settings files:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;settings.py&lt;/li&gt;
&lt;li&gt;local_settings.py&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The former maintains all the application wide settings. The latter is the
override, allowing the developer to override various settings on her machine,
and allowing the various stages of your environment (dev, staging, production)
to have their own &lt;cite&gt;local_settings.py&lt;/cite&gt; file defining environment specific
setting values (think database settings, filesystem settings, debugging, etc).&lt;/p&gt;
&lt;p&gt;This has been a convention I've come across a few times before when looking at
other projects, so I stuck with this basic pattern.&lt;/p&gt;
&lt;p&gt;But it's not the final answer. If you were to take a look at Daniel Lindsey's
blog post &lt;a class="reference external" href="http://toastdriven.com/fresh/better-local-settings/"&gt;Better Local Settings&lt;/a&gt; you'll see one proposed solution. Then read
the comments of his post and you'll see a few other solutions, highlighting the
fact that we need a standard. In fact, the popular &lt;a class="reference external" href="http://djangodose.com"&gt;DjangoDose&lt;/a&gt; podcast proposed
their solution in their &lt;a class="reference external" href="http://djangodose.com/articles/2009/09/handling-development-staging-and-production-enviro/"&gt;Handling Development, Staging, and Production
Environments&lt;/a&gt; using the FLAVOR concept. But again, take a peek at the comments
and you'll see another handful of alternative solutions used by other
developers.&lt;/p&gt;
&lt;p&gt;A contributer to Mingus suggested I take a look at the &lt;a class="reference external" href="http://trac.transifex.org/"&gt;Transifix&lt;/a&gt; team's
documentation &lt;a class="reference external" href="http://code.djangoproject.com/wiki/SplitSettings#UsingalistofconffilesTransifex"&gt;Using a list of conf files&lt;/a&gt; on how they manage their settings
files as a best practice, which looks interesting as well. The simple fact
that wiki page for various solutions in managing your settings files even
exists highlights the need for a standard.&lt;/p&gt;
&lt;p&gt;One project that recently found its way on my radar is &lt;a class="reference external" href="http://github.com/tarequeh/django-config"&gt;Django-Config&lt;/a&gt; from
Nowell Strite, Shawn Rider and now supported by Tareque Hossain. Strite and
Rider both work at PBS and recently detailed the obstacles they run into
supporting the various projects and reusable apps across their infrastructure
with their &lt;a class="reference external" href="http://blip.tv/file/3040424"&gt;Pluggable, Reusable Django Apps: A Use Case and Proposed Solution&lt;/a&gt;
presentation at DjangoCon 2009.&lt;/p&gt;
&lt;p&gt;Django-Config defines itself as &amp;quot;...an easy way to maintain multiple
configurations for django. It relies on the concept of having a shared
configuration file (base) and a per user/ server custom configuration file
(dev1/ dev2/ local/ staging). settings.py combines the base &amp;amp; custom
configuration and loads it up.&amp;quot; I have yet to give the project a run myself
but assuming the complexity of the infrastructure that PBS maintains
I'm going to believe that there's a few nuggets of tested and refined goodies
in there.&lt;/p&gt;
&lt;p&gt;So I'm left not knowing what to do. For now, I'll keep with the basic
implementation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="static-media-no-you-didnt"&gt;
&lt;h1&gt;Static Media? No you didn’t!&lt;/h1&gt;
&lt;p&gt;Anyone who has ever authored a Django reusable app has asked themselves the
question, where do I put the static media? What do I name the directory? Do I
name it /media/ or do I name it /static/? Where do I place it on my file
system?&lt;/p&gt;
&lt;p&gt;A perfect example is Simon Willison's django-cropper reusable app I recently
integrated into Mingus. Willison recently left this git &lt;a class="reference external" href="http://github.com/simonw/django_cropper/commit/ef9e5334a333f40668dccfb9d6d00ef9ce72e0a2"&gt;commit message&lt;/a&gt;,
&amp;quot;Finally managed to get the package to include the template... no idea what I
should do with the static file dependencies though&amp;quot;. It's a good question.
What does a developer do with static media dependencies? Do they include the
files in their project? Do they tell the user to go download them from XYZ? If
they do include the files, where do they place them in their app?&lt;/p&gt;
&lt;p&gt;I believe there is an answer... &lt;a class="reference external" href="http://github.com/jezdez/django-staticfiles"&gt;Django-StaticFiles&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The project stems from the &lt;a class="reference external" href="http://pinaxproject.com"&gt;Pinax&lt;/a&gt; project that faces this same obstacle in a
much larger scale. So if anyone knows a solution, the Pinax crew would. I'm not
going to dive into the finer details of the project, as it provides a terrific
set of features and functionality, but what it outlines in its implementation
is an easy to follow standard for reusable apps and static media management.
Maybe it should become a contrib app, or at least the convention we all look
to?&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="upload-this-pal"&gt;
&lt;h1&gt;Upload this pal&lt;/h1&gt;
&lt;p&gt;While we're here talking about media management, let's also talk about files
uploaded via the Django admin. I believe we should also have a default
convention here too &amp;#8212; the /uploads/ directory off MEDIA_ROOT. Far too often
I'll grab an application that has this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;photo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ImageField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upload_to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/images/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That helps no one. The convention should be &lt;cite&gt;MEDIA_ROOT + &amp;quot;/uploads/app_name/&amp;quot;&lt;/cite&gt;
as the default, and any directory defined in the &lt;cite&gt;upload_to&lt;/cite&gt; parameter is
appended to the default, like so (in my photobooth app):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;photo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ImageField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upload_to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;images&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By default this would result in &lt;cite&gt;MEDIA_ROOT + /uploads/photobooth/images/&lt;/cite&gt; file
path.&lt;/p&gt;
&lt;p&gt;I'm simplifying the underlying complexity, obviously, but I do believe a sane
default would provide better asset management, and again make reusable app
integration less invasive for these cases.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="i18n-gets-no-respect"&gt;
&lt;h1&gt;i18n gets no respect&lt;/h1&gt;
&lt;p&gt;I'll make this as short and sweet as possible. The &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/i18n/"&gt;internationalization&lt;/a&gt;
features in Django are amazing. Having built one multi-lingual site from the
ground up, and benefitting from the features Django provides out of the box
for this i18n, it's a damn shame more reusable apps don't internationalize
their app from the start (and I'm to blame here myself &amp;#8212; let's just be
honest).&lt;/p&gt;
&lt;p&gt;Here's the two simplest ways to at least lay the groundwork for
internationalizing your application. Let's take a &lt;cite&gt;models.py&lt;/cite&gt; for this example.
All you need to do is this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.utils.translation&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ugettext_lazy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;description), help_text=_(&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;your&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;))&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;verbose_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;post&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;verbose_name_plural&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;posts&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now in your templates all you need to do for the text laying around is this,
example landing.html:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;load&lt;/span&gt; &lt;span class="nv"&gt;i18n&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;h4&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;trans&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Blog roll&amp;quot;&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h4&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And that's about it. As always, there's a little more under the hood, so make
sure to read the docs which covers everything you need to know in getting
started, but for the most part the above gets your app 80-90% of the way there.&lt;/p&gt;
&lt;p&gt;And if you are deploying a multi-lingual application you will want to take a
look at these apps:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="http://code.google.com/p/django-rosetta/"&gt;Django-Rosetta&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://github.com/citylive/django-datatrans"&gt;Django-DataTrans&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And take a look at this excellant article which reviews a handful of reusable
apps to help you with i18n integration &amp;#8212; &lt;a class="reference external" href="http://www.muhuk.com/2010/01/dynamic-translation-apps-for-django/"&gt;Dynamic Translation Apps for
Django&lt;/a&gt;. The fact is that if you are not internationalizing your app then you
are a bad person. No, but seriously, if you aren't internationalizing your app
you are creating a headache for another developer, and more importantly you are
also limiting the potential adoption of your project. So be a good person and
internationalize that bad boy.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="aint-nothing-but-a-migrations-thing"&gt;
&lt;h1&gt;Ain’t nothing but a Migrations thing&lt;/h1&gt;
&lt;p&gt;We have to start including South migrations in all our reusable apps we
publish. Or we need my pony request to be fulfilled (discussed below). I've
pitched this pony request once before in my &lt;a class="reference external" href="http://blog.montylounge.com/2009/oct/21/south-and-reusable-apps/"&gt;South and Reusable Apps&lt;/a&gt; post but
I wanted to reiterate the importance of the community selecting a migration
tool.&lt;/p&gt;
&lt;p&gt;As we discussed on the &lt;a class="reference external" href="http://djangodose.com/blog/2009/10/reusable-application-panel/"&gt;Reusable Apps in Django Panel&lt;/a&gt; on DjangoDose the
current best-in-show migration tool is &lt;a class="reference external" href="http://south.aeracode.org/"&gt;South&lt;/a&gt;. There is currently no easy way
to migrate a collection of reusable apps since migration management isn't a
discipline I've found practiced in most apps. And again, I'm to blame for this
as well. But no more. Moving forward I'm putting my eggs in the South basket.&lt;/p&gt;
&lt;p&gt;Now, South could provide a feature that makes this rather easy for us
developers. That is the proposition I made in the aforementioned blog post.
Andrew Godwin, the author of South, commented that the solution for migrating
reusable apps that don't employ South themselves is already in the works in a
forthcoming version of South. So all hope is not lost. This feature would allow
us developers to generate South migrations for the reusable apps we leverage
even if they don't make use of South themselves. Terrific!&lt;/p&gt;
&lt;p&gt;Right now Mingus provides only one migration (raw sql) and that's because it
wasn't until recently that people started using Mingus as their blog engine.
And knowing this it would be negligent of me to not provide migrations for
these users looking to upgrade to the next Mingus release. So at least they
have raw sql to work with, but it's not the right answer. The right answer is a
standard migration tool we all use.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="cache-keys-rule-everything-around-me"&gt;
&lt;h1&gt;Cache Keys Rule Everything Around Me&lt;/h1&gt;
&lt;p&gt;The Django &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/cache/"&gt;cache framework&lt;/a&gt; provides a tremendous amount of caching
functionality and flexibility. The one thing I often hear developers
reiterating is to make sure your cache keys are named properly so to avoid
cache key conflicts. You want unique cache keys that can be recalled easily for
cache validation/invalidation, querying, etc.&lt;/p&gt;
&lt;p&gt;So why not include a helper to ease this? That exactly what I did when I added
&lt;a class="reference external" href="http://github.com/montylounge/django-sugar/blob/master/sugar/cache/utils.py#L27"&gt;create_cache_key&lt;/a&gt; to &lt;a class="reference external" href="http://github.com/montylounge/django-sugar/"&gt;django-sugar&lt;/a&gt;. The method actually combines the code of
one blog post and a reusable app:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="http://richwklein.com/2009/08/04/improving-django-cache-part-ii/"&gt;Improving Django Cache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://github.com/mmalone/django-caching/"&gt;Django-Caching&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here's a look at the api:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;blog.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt;
&lt;span class="n"&gt;slug_val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;some-slug&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;mykey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_cache_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;slug&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;slug_val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mykey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What the above &lt;cite&gt;create_cache_key&lt;/cite&gt; does is accept either a Model or Manager as
its first argument, the field you are interested in as its 2nd argument, and
the field value as its 3rd argument. Based on that it can generate, and
regenerate a cache key. The benefit here is that it isolates the logic for
remembering cache key names. It handles the construction for you.&lt;/p&gt;
&lt;p&gt;This may not be the best solution possible or the most complete solution, but
it's a solution that begs the question: why don't we have a similar utility
method in Django itself that we reference by default so we don't have to be
concerned about clashing cache key values in our apps?&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;The reason I love hacking on Mingus is Django... I love Django, and Python.
So the above &amp;quot;hates&amp;quot; are really just small bumps in the road of an amazingly
smooth ride that Django provides.&lt;/p&gt;
&lt;p&gt;The future of Mingus is a final 1.0 release which will include any bug fixes
that pop up, more documentation, more tests, and other than that I don't
think there's much left to add to something that's not really anything more
than a concept project. I believe the current feature set is final.&lt;/p&gt;
&lt;p&gt;For those who manage any open source project, big or small, I tip my hat to you
and thank you. Just like you I'm excited for all the amazing things coming in
Django 1.2 and as a consumer of such a terrific open source project, I feel lucky
that I get to work with Django daily. In ending this I just realized I was
&amp;quot;that guy&amp;quot; for most of this article and I hate myself for it.&lt;/p&gt;
&lt;table class="docutils footnote" frame="void" id="id5" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Even if it's an itsy bitsy one.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id6" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Since my docs reference these, I assume that by following the docs you
forced yourself to play with these excellent tools.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id7" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id3"&gt;[3]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Eating your own dog food.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id8" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id4"&gt;[4]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;At this point it's arguably no longer reusable, or actually maybe more
reusable now that I think about it.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</summary></entry><entry><title>Smoothing The Curve</title><link href="http://djangoadvent.com/1.2/smoothing-curve/" rel="alternate" /><updated>2010-02-11T00:00:00-11:00</updated><author><name>Sean O'Connor</name><uri>http://seanoc.com</uri></author><id>http://djangoadvent.com/1.2/smoothing-curve/</id><summary type="html">&lt;p&gt;For nearly all of the tools provided by Django, there are hooks provided to
allow for incremental modification and extension.  Very rarely do you ever need
to rewrite a significant amount of functionality within Django, simply to
change the behavior of a tool.  For example, if you want change the way a form
will look, you can change a widget from the default, create a custom field, or
just use your own HTML.  With each option, you can override a bit more
functionality but still take advantage of everything else the forms library
provides.&lt;/p&gt;
&lt;p&gt;You can visualize these incremental options as a curve.  At one end you have a
stock form which is simple to write but provides limited control.  At the other
end, you have a custom form class with static HTML which provides much more
control but is more complicated to create.  In the case of forms this is a
pretty smooth curve since there are options to incrementally replace all of the
functionality of the library.&lt;/p&gt;
&lt;p&gt;Before Django 1.2 the ORM had a similar curve with one exception &amp;#8212; it had a bit
of a cliff at the end.  In particular, if you got to the point where you needed
to just write a custom SQL query you needed to go completely outside the ORM.
While this wasn't horrible, there was functionality which one would still want
from the ORM which one had to now rebuild on their own.  With Django 1.2, a
&lt;tt class="docutils literal"&gt;Model.objects.raw()&lt;/tt&gt; method has been added to address this problem and
smooth out the ORM's curve.&lt;/p&gt;
&lt;div class="section" id="the-old-way"&gt;
&lt;h1&gt;The Old Way&lt;/h1&gt;
&lt;p&gt;Before Django 1.2 if you needed to do a raw SQL query, you needed to do
something like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;library.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;

&lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;SELECT * FROM library_author&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetchall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;authors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now this isn't horrible, but we have lost access to functionality in the ORM
beyond the ability to generate SQL queries.  In particular, we've lost the
automatic transformation of the results of our query into model instances.
There are ways we could replicate the lost functionality without too much work
but we'd be reinventing the wheel.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-new-way"&gt;
&lt;h1&gt;The New Way&lt;/h1&gt;
&lt;p&gt;In Django 1.2 to perform a raw SQL query, you can do something like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;library.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;

&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;SELECT * FROM library_author&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;authors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The result here, &lt;tt class="docutils literal"&gt;authors&lt;/tt&gt;, is a &lt;tt class="docutils literal"&gt;RawQuerySet&lt;/tt&gt;.  &lt;tt class="docutils literal"&gt;RawQuerySet&lt;/tt&gt; is much
like &lt;tt class="docutils literal"&gt;QuerySet&lt;/tt&gt; in that it is an iterable object which returns a model
instance from the result set with each iteration.  It is not like a
&lt;tt class="docutils literal"&gt;QuerySet&lt;/tt&gt; in that it cannot be chained.  Since the query isn't being built
programatically anymore, chaining doesn't make sense.&lt;/p&gt;
&lt;p&gt;Similar to a raw database cursor, we can provide a collection of parameters to
the raw method and Django will safely quote/escape them.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;SELECT * FROM library_author WHERE first_name = &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;bob&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
&lt;span class="n"&gt;authors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So this is great! We're not reinventing the wheel, we're protected from SQL
injection attacks, and we have the model instances we want.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="but-wait-there-s-more"&gt;
&lt;h1&gt;“But wait, there's more!”&lt;/h1&gt;
&lt;p&gt;Like most things in Django, the &lt;tt class="docutils literal"&gt;raw()&lt;/tt&gt; method offers some additional
functionality to help with corner cases or particularly complex queries:&lt;/p&gt;
&lt;div class="section" id="field-order-independence"&gt;
&lt;h2&gt;Field order independence&lt;/h2&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;Model.objects.raw()&lt;/tt&gt; doesn't care what order fields are returned in by the
query, all that matters is that the query field names match up to a field on
the model.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# All of these queries will work the same&lt;/span&gt;
&lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;SELECT * FROM library_author&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;SELECT id, first_name, last_name FROM library_author&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;SELECT last_name, id, first_name FROM library_author&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="annotations"&gt;
&lt;h2&gt;Annotations&lt;/h2&gt;
&lt;p&gt;If a query returns any fields which do not exist in the model class, they are
added as annotations to the model instances returned by the &lt;tt class="docutils literal"&gt;RawQueryset&lt;/tt&gt;.
This allows you to easily take advantage of operations or calculations which
are more efficient to perform within the database.&lt;a class="footnote-reference" href="#id4" id="id1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;authors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;SELECT *, age(birth_date) as age FROM library_authors&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; is &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;.&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;John&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="mf"&gt;37.&lt;/span&gt;
&lt;span class="n"&gt;Jane&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="mf"&gt;42.&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="field-mappings"&gt;
&lt;h2&gt;Field Mappings&lt;/h2&gt;
&lt;p&gt;If for whatever reason, your query field names cannot exactly match your model
field names, &lt;tt class="docutils literal"&gt;Model.objects.raw()&lt;/tt&gt; provides a facility for mapping query
fields to model fields.&lt;a class="footnote-reference" href="#id5" id="id2"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To map query fields to model fields, one simply needs to pass a dictionary
containing the translations to the &lt;tt class="docutils literal"&gt;raw()&lt;/tt&gt; method.  Only fields which don't
match model fields need to have translations provided.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;field_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;first&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;first_name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;last&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;last_name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;SELECT id, first_name AS first, last_name as last FROM library_author&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;authors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;translations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;field_map&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="deferred-fields"&gt;
&lt;h2&gt;Deferred Fields&lt;/h2&gt;
&lt;p&gt;Any fields which are expected by the model, but are not returned by the query,
are marked as &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/ref/models/querysets/#queryset-defer"&gt;deferred&lt;/a&gt;.
Deferred fields are only fetched when the model instance's field is accessed.
This is useful in cases where you may not be pulling data from the “real” table
for the model or when you have very large tables.  Be aware that primary keys
cannot be deferred and must be returned by all queries.  If a query doesn't
return a primary key, an &lt;tt class="docutils literal"&gt;InvalidQuery&lt;/tt&gt; exception will be raised.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="limitations"&gt;
&lt;h1&gt;Limitations&lt;/h1&gt;
&lt;p&gt;There are a few limitations placed on what &lt;tt class="docutils literal"&gt;raw()&lt;/tt&gt; can do.  The biggest of
which is that &lt;tt class="docutils literal"&gt;raw()&lt;/tt&gt; will only allow &lt;tt class="docutils literal"&gt;SELECT&lt;/tt&gt; queries.  If any other type
of query is attempted via &lt;tt class="docutils literal"&gt;raw()&lt;/tt&gt;, an &lt;tt class="docutils literal"&gt;InvalidQuery&lt;/tt&gt; exception will be
raised.  This is done partially because it doesn't make sense to return model
instances for anything other than &lt;tt class="docutils literal"&gt;SELECT&lt;/tt&gt; queries but it is primarily done
as a deterrent.  Modifying data with raw SQL is very much something which
should be an absolute last resort in Django.  Accordingly we didn't want to
encourage the practice by making it any easier to do so.  If you really need to
perform raw SQL queries which are not &lt;tt class="docutils literal"&gt;SELECT&lt;/tt&gt; queries, you can still get a
raw database cursor and go from here.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="that-s-all-folks"&gt;
&lt;h1&gt;That's all folks&lt;/h1&gt;
&lt;p&gt;There you have it.  Now in Django 1.2, you can much more easily perform raw SQL
queries when you need to.  The curve has been smoothed.  Official documentation
for this new feature can be found on the &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/db/sql/#topics-db-sql"&gt;raw SQL&lt;/a&gt; page.&lt;a class="footnote-reference" href="#id6" id="id3"&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;table class="docutils footnote" frame="void" id="id4" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Example heavily stolen from the &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/db/sql/#django.db.models.Manager.raw"&gt;django docs&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id5" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;It's worth noting here that when the term &amp;quot;model fields&amp;quot; is used, it
means the database field name that the Django ORM is expecting to exist in the
database, not necessarily the name of the python attribute on the model class.
If you've overridden a field name using &lt;tt class="docutils literal"&gt;db_column&lt;/tt&gt;, the override name is
what the &lt;tt class="docutils literal"&gt;raw()&lt;/tt&gt; method will be expecting.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id6" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id3"&gt;[3]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Thanks to Jacob Kaplan-Moss for finishing the &lt;tt class="docutils literal"&gt;raw()&lt;/tt&gt; work where I
left it off and to Russell Keith-Magee for contributing the code to handle
deferred fields.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</summary></entry><entry><title>Messages for the rest of us</title><link href="http://djangoadvent.com/1.2/messages-rest-us/" rel="alternate" /><updated>2010-02-10T00:00:00-11:00</updated><author><name>Jeff Croft</name><uri>http://jeffcroft.com/</uri></author><id>http://djangoadvent.com/1.2/messages-rest-us/</id><summary type="html">&lt;p&gt;In today's world of web applications, it is frequently necessary to send
notifications to visitors. From “Your comment has been received, and is
awaiting moderation,” to “Thanks for your interest, we'll send you an invite
when we launch,” these little messages show up all the time, and it’s nice to
have a consistent interface to sending and displaying them for your users.&lt;/p&gt;
&lt;p&gt;Django's bundled authentication and authorization app (&lt;cite&gt;django.contrib.auth&lt;/cite&gt;)
has always included basic functionality to send simple messages to users, but
it had some pretty serious knocks against it. Django 1.2 now includes a brand
new messaging framework, written primarily by Tobias McNulty, that makes
sending these types of notifications painless and flexible.&lt;/p&gt;
&lt;div class="section" id="what-was-wrong-with-the-old-way"&gt;
&lt;h1&gt;What was wrong with the old way?&lt;/h1&gt;
&lt;p&gt;Because the legacy messaging system is part of &lt;cite&gt;django.contrib.auth&lt;/cite&gt;, you must
install that app in order to use it. But there are plenty of instances in which
you may not need authentication and authorization, but you do need messaging.
Or perhaps you prefer to use your own auth app, instead of the one included
with Django. Or, you want to use &lt;cite&gt;django.contrib.auth&lt;/cite&gt; but don't want to use
messages. Django 1.2's messaging framework allows for these configurations.&lt;/p&gt;
&lt;p&gt;Additionally, the legacy system stores and retrieves these messages from the
database. While this is fine for many projects, it does mean that most every
page view incurs an additional database hit &amp;#8212; which is simply unnecessary, in
most cases. Django 1.2 provides options for storing messages outside the
database to avoid this performance hit.&lt;/p&gt;
&lt;p&gt;What's more, in previous versions of Django all messages are treated equally.
There is no way to indicate a “type” or “level” for a message &amp;#8212; for example,
to differentiate between an error message and a success message. The new
messaging framework provides this feature.&lt;/p&gt;
&lt;p&gt;Finally, Django 1.1's messaging system associates each message with a
particular user. Therefore, you are limited to sending messages to logged-in
users. In Django 1.2, you're able to send messages to visitors regardless of
whether or not they're signed in.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="getting-started-with-the-new-messaging-framework"&gt;
&lt;h1&gt;Getting started with the new messaging framework&lt;/h1&gt;
&lt;p&gt;Messaging is enabled by default for new projects created with &lt;cite&gt;django-admin.py
startproject&lt;/cite&gt;. So if you're just starting your project with Django 1.2,
messaging is already enabled! If you've got an existing project, or create your
projects another way, enabling messaging functionality is very simple. Just
complete these three steps:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Add &lt;cite&gt;‘django.contrib.messages.middleware.MessageMiddleware’&lt;/cite&gt; to
&lt;cite&gt;MIDDLEWARE_CLASSES&lt;/cite&gt; in your settings file.&lt;/li&gt;
&lt;li&gt;Add &lt;cite&gt;‘django.contrib.messages.context_processors.messages’&lt;/cite&gt; to
&lt;cite&gt;TEMPLATE_CONTEXT_PROCESSORS&lt;/cite&gt; in your settings file.&lt;/li&gt;
&lt;li&gt;Add &lt;cite&gt;‘django.contrib.messages’&lt;/cite&gt; to &lt;cite&gt;INSTALLED_APPS&lt;/cite&gt; in your settings file.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="sending-messages"&gt;
&lt;h1&gt;Sending messages&lt;/h1&gt;
&lt;p&gt;Sending messages to visitors with the new framework is also simple, especially
if you want to use one of Django's five built-in message levels (&lt;cite&gt;DEBUG&lt;/cite&gt;,
&lt;cite&gt;INFO&lt;/cite&gt;, &lt;cite&gt;SUCCESS&lt;/cite&gt;, &lt;cite&gt;WARNING&lt;/cite&gt;, and &lt;cite&gt;ERROR&lt;/cite&gt;. More on message level later).&lt;/p&gt;
&lt;p&gt;To send a success message to a visitor's request, simply call:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.contrib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;
&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Skadoosh! You&amp;#39;ve updated your profile!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Likewise for the other default message levels:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Yo! There are new comments on your photo!&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Doh! Something went wrong.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Bam! &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; objects were modified.&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;modified_count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Uh-oh. Your account expires in &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; days.&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;expiration_days&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since messages are added to the request, you'll need to have access to a
request object (as you do in every Django view).&lt;/p&gt;
&lt;p&gt;If you're upgrading code which used the legacy messaging system, there are two
steps:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;In each view that sends messages, add &lt;cite&gt;from django.contrib import messages&lt;/cite&gt;
to the top of the file.&lt;/li&gt;
&lt;li&gt;Replace each instance of &lt;cite&gt;request.user.message_set.create(message=message)&lt;/cite&gt;
with the new API, such as &lt;cite&gt;message.error(request, message)&lt;/cite&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="displaying-messages"&gt;
&lt;h1&gt;Displaying messages&lt;/h1&gt;
&lt;p&gt;To display messages in a template, use code along these lines:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;messages&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;messages&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;message&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;messages&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;message.tags&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;message.tags&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;endif&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;message&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;endfor&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;endif&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It usually makes sense to put this message template code in your base template,
so all templates that extend it will display messages.&lt;/p&gt;
&lt;p&gt;The code is nearly identical to what you may have been using with Django 1.1,
but you'll note the new &lt;cite&gt;tags&lt;/cite&gt; attribute for each message. Django 1.2
associates each message level with a string representation for use in your HTML
template&lt;a class="footnote-reference" href="#id3" id="id1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;. Here, we output the tags as
classes, which can then be used for individual styling of different message
levels:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nc"&gt;.messages&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="nc"&gt;.error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.messages&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="nc"&gt;.success&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If all you want to do is send some basic messages, you don't have to read any
farther. That's really all there is to it. It’s simple and very flexible.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-message-storage-engine"&gt;
&lt;h1&gt;The message storage engine&lt;/h1&gt;
&lt;p&gt;Django provides a handful of backend storage systems for messages &amp;#8212; and it’s
also easy to write your own. The &lt;cite&gt;LegacyFallbackStorage&lt;/cite&gt; engine Django uses as
the default is sensible and appropriate for most projects. However, there are
reasons why you may want to switch engines, so it’s good to understand the
options:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;cite&gt;django.contrib.messages.storage.session.SessionStorage&lt;/cite&gt;: This engine stores
all messages in the request's session. Therefore, it requires the
&lt;cite&gt;django.contrib.sessions&lt;/cite&gt; app be installed (since it’s enabled by default, most
projects are already using it). By default, sessions are stored in the
database, so using this storage option does require a database hit each time
you check for messages in a template (i.e. &lt;cite&gt;{% if messages %}&lt;/cite&gt;).&lt;/li&gt;
&lt;li&gt;&lt;cite&gt;django.contrib.messages.storage.cookie.CookieStorage&lt;/cite&gt;: This engine stores
all messages in a cookie. Therefore, it does not require a hit to the database,
providing better performance than &lt;cite&gt;SessionStorage&lt;/cite&gt;. However, cookies can only
be 4096 bytes in length, so when a user's message exceed 4096 bytes, messages
will not be delivered.&lt;/li&gt;
&lt;li&gt;&lt;cite&gt;django.contrib.messages.storage.fallback.FallbackStorage&lt;/cite&gt;: This engine first
uses &lt;cite&gt;CookieStorage&lt;/cite&gt;, but falls back to &lt;cite&gt;SessionStorage&lt;/cite&gt; in the event all
message could not fit in a single cookie.&lt;/li&gt;
&lt;li&gt;&lt;cite&gt;django.contrib.messages.storage.user_messages.LegacyFallbackStorage&lt;/cite&gt;: This
engine is provided for backwards compatibility with Django 1.1 and earlier. It
works exactly like &lt;cite&gt;FallbackStorage&lt;/cite&gt;, but also retrieves messages from the
legacy messaging system in &lt;cite&gt;django.contrib.auth&lt;/cite&gt;. This provides compatibility
with any applications that haven't yet been updated to use the new messages
framework. Like the messaging system in &lt;cite&gt;django.contrib.auth&lt;/cite&gt;, this engine is
deprecated, and will be removed in Django 1.4. In the meantime, it’s the
default storage method for the new messages framework. When it’s removed in
1.4, &lt;cite&gt;FallbackStorage&lt;/cite&gt; will become the new default.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="message-levels-and-tags"&gt;
&lt;h1&gt;Message levels and tags&lt;/h1&gt;
&lt;p&gt;As noted earlier, Django includes five common message levels by default. Each
level is an integer. You can easily extend or modify these for your own needs.
The default message levels map to the following integers:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;DEBUG: 10&lt;/li&gt;
&lt;li&gt;INFO: 20&lt;/li&gt;
&lt;li&gt;SUCCESS: 25&lt;/li&gt;
&lt;li&gt;WARNING: 30&lt;/li&gt;
&lt;li&gt;ERROR: 40&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To add your own message level, define a constant and then use the
&lt;cite&gt;add_message()&lt;/cite&gt; method to send a message using it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;CRITICAL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;
&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CRITICAL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;OH NOES! A critical error occurred.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you want to use the message level in HTML or CSS, as we did above, you'll
also want to add &lt;cite&gt;MESSAGE_TAGS&lt;/cite&gt; to your settings file to provide a mapping
between your levels and the tag you want outputted in your templates:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;MESSAGE_TAGS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;critical&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="in-conclusion"&gt;
&lt;h1&gt;In conclusion&lt;/h1&gt;
&lt;p&gt;The new messaging framework included in Django 1.2 is not a particularly
complex piece, but it does provide functionality that is absolutely essential
in today's word of web apps, and it does so in an elegant, clean, and simple
way. What's more, it’s completely backwards-compatible with the legacy system,
so you don't have to worry about old code or third-party apps breaking when you
upgrade to 1.2. Be aware, though, that this compatibility layer will be removed
in 1.4 &amp;#8212; slated for release sometime in 2027.&lt;a class="footnote-reference" href="#id4" id="id2"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Joking. Enjoy Django 1.2, everyone. It really is a great update to our favorite framework.&lt;/p&gt;
&lt;table class="docutils footnote" frame="void" id="id3" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Ostensibly for CSS and JavaScript hooks.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="id4" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;em&gt;Late&lt;/em&gt; 2027, if I had to guess.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</summary></entry><entry><title>Multiple Database Support</title><link href="http://djangoadvent.com/1.2/multiple-database-support/" rel="alternate" /><updated>2010-02-09T00:00:00-11:00</updated><author><name>Alex Gaynor</name><uri>http://alexgaynor.net/</uri></author><id>http://djangoadvent.com/1.2/multiple-database-support/</id><summary type="html">&lt;p&gt;Since Django's creation there's been an implicit restriction to a single
database (this is as systemic as things like the &lt;tt class="docutils literal"&gt;DATABASE_*&lt;/tt&gt; family of
settings), and for almost as long support for multiple databases has been
requested.  This summer, as a part of the &lt;a class="reference external" href="http://code.google.com/soc/"&gt;Google Summer of Code&lt;/a&gt;, multiple
database support was implemented, and as a part of the 1.2 process it was
merged into trunk.  These changes involve a ton of changes to the internals,
and a few well placed extensions to the existing public API.&lt;/p&gt;
&lt;div class="section" id="the-multi-db-public-api"&gt;
&lt;h1&gt;The Multi-DB Public API&lt;/h1&gt;
&lt;p&gt;The most obvious change to Django is that instead of defining your database
settings like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;DATABASE_ENGINE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;postgresql_psycopg2&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;DATABASE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;my_big_project&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;DATABASE_USER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;mario&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;DATABASE_PASSWORD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;princess_peach&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You instead write something like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;DATABASES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;&amp;quot;default&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;&amp;quot;ENGINE&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;django.db.backends.postgresql_psycopg2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;&amp;quot;NAME&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;my_big_project&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;&amp;quot;USER&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;mario&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;&amp;quot;PASSWORD&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;princess_peach&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s"&gt;&amp;quot;credentials&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;&amp;quot;ENGINE&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;django.db.backends.oracle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;&amp;quot;NAME&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;users&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All projects will eventually need to be migrated these new settings, although
the old style will continue to work until Django 1.4.  The only key with
special significance in the &lt;tt class="docutils literal"&gt;DATABASES&lt;/tt&gt; dictionary is &lt;tt class="docutils literal"&gt;&amp;quot;default&amp;quot;&lt;/tt&gt; &amp;#8212; if
you're using databases you need to define a &lt;tt class="docutils literal"&gt;&amp;quot;default&amp;quot;&lt;/tt&gt; database.&lt;/p&gt;
&lt;p&gt;Now that you've told Django about all your databases you need a way to tell
Django when to use them.  The first addition in this arena is the &lt;tt class="docutils literal"&gt;using()&lt;/tt&gt;
method on &lt;tt class="docutils literal"&gt;QuerySets&lt;/tt&gt;.  &lt;tt class="docutils literal"&gt;using()&lt;/tt&gt; takes a single parameter, a database
alias (alises are the keys of the &lt;tt class="docutils literal"&gt;DATABASES&lt;/tt&gt; dictionary), and it binds the
&lt;tt class="docutils literal"&gt;QuerySet&lt;/tt&gt; to that database.  Like every other &lt;tt class="docutils literal"&gt;QuerySet&lt;/tt&gt; method it can be
chained at will (like the &lt;tt class="docutils literal"&gt;order_by()&lt;/tt&gt; method calling it a second time it
overides the first call).  This basically gives you complete control to define
where models are read from (and if you get tricky with &lt;tt class="docutils literal"&gt;create()&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;delete()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;update()&lt;/tt&gt; even the ability to control writes):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username__startswith&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;admin&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;credentials&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In addition to this new &lt;tt class="docutils literal"&gt;QuerySet&lt;/tt&gt; method &lt;tt class="docutils literal"&gt;delete()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;save()&lt;/tt&gt; on
models takes a new &lt;tt class="docutils literal"&gt;using&lt;/tt&gt; parameter, which is, again, a database alias.&lt;/p&gt;
&lt;p&gt;There is also a new method on &lt;tt class="docutils literal"&gt;Managers&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;db_manager()&lt;/tt&gt;, this again takes
a database alias and what it does is very similar to &lt;tt class="docutils literal"&gt;using()&lt;/tt&gt;.  The key
difference is that instead of returning a &lt;tt class="docutils literal"&gt;QuerySet&lt;/tt&gt; it returns a new
&lt;tt class="docutils literal"&gt;Manager&lt;/tt&gt;.  The use case for this is being able to chain it with methods on
&lt;tt class="docutils literal"&gt;Managers&lt;/tt&gt; that don't return a &lt;tt class="docutils literal"&gt;QuerySet&lt;/tt&gt;, such as &lt;tt class="docutils literal"&gt;create_user()&lt;/tt&gt; on the
&lt;tt class="docutils literal"&gt;UserManager&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="database-routers"&gt;
&lt;h1&gt;Database Routers&lt;/h1&gt;
&lt;p&gt;By using all of these methods you can implement any sort of multiple database
system you want, master-slave replication, partitioning, sharding, or anything
else.  However, it wouldn't necessarily be convenient.  You'd have to litter
your codebase with calls to &lt;tt class="docutils literal"&gt;using()&lt;/tt&gt;, and that doesn't play nicely with
Django's reusable application philosophy (it was for this reason that a
&lt;tt class="docutils literal"&gt;using&lt;/tt&gt; option was removed from the &lt;tt class="docutils literal"&gt;Meta&lt;/tt&gt; class in Django models).  In
addition there are some places where you don't have an explicit &lt;tt class="docutils literal"&gt;QuerySet&lt;/tt&gt;,
for example &lt;tt class="docutils literal"&gt;my_obj.user&lt;/tt&gt; will create a &lt;tt class="docutils literal"&gt;QuerySet&lt;/tt&gt; behind the scenes to
access the &lt;tt class="docutils literal"&gt;User&lt;/tt&gt; model, but you don't have any place to call &lt;tt class="docutils literal"&gt;using()&lt;/tt&gt;
there.  For these reason the concept of a &amp;quot;database router&amp;quot; was introduced.
Database routers take whatever is available about the query you want to
perform, and they can say what database it should go to.  Database routers are
setup in your settings file with a new &lt;tt class="docutils literal"&gt;DATABASE_ROUTERS&lt;/tt&gt; setting, which is a
list of database routers:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;DATABASE_ROUTERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s"&gt;&amp;quot;path.to.AuthRouter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;&amp;quot;path.to.MasterSlaveRouter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;DATABASE_ROUTERS&lt;/tt&gt; is a list because at any stage a router can return
&lt;tt class="docutils literal"&gt;None&lt;/tt&gt; and then Django will fall back to the next router in the list.  These
routers can define a few different methods:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;db_for_read&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;db_for_write&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;allow_relation&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;allow_syncdb&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first two are fairly self-explanitory, they return the alias that that
query should be performed against.  The &lt;tt class="docutils literal"&gt;allow_relation&lt;/tt&gt; method exists to
provide a sanity check.  Django doesn't want to let you assign cross-database
relations if it's going to fail.  Therefore when you're trying to create a
relationship between two models on different databases (for either a
&lt;tt class="docutils literal"&gt;ForeignKey&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;ManyToManyField&lt;/tt&gt;) Django will call this method so that you
can provide the appropriate validation.  The final method, &lt;tt class="docutils literal"&gt;allow_syncdb&lt;/tt&gt;,
provides a way for you to let Django know which models should be sync'd (and
therefore available) on which database.&lt;/p&gt;
&lt;p&gt;As always the Django documentation on &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/db/multi-db/"&gt;multiple databases&lt;/a&gt; provides great
examples of how to use all these things, including examples of how they're
used, and how to get started implementing some common patterns with database
routers.  The addition of multiple databases should provide a tremendous boon
for the Django community, allowing Django to be used in yet more enviroments.&lt;/p&gt;
&lt;/div&gt;
</summary></entry><entry><title>Welcome to Django-Advent</title><link href="http://djangoadvent.com/1.2/welcome-django-advent/" rel="alternate" /><updated>2010-02-08T00:00:00-11:00</updated><author><name>Jacob Kaplan-Moss</name><uri>http://jacobian.org/</uri></author><id>http://djangoadvent.com/1.2/welcome-django-advent/</id><summary type="html">&lt;p&gt;I'm incredibly excited about the release of Django 1.2. Looking back, there've
been a few moments that turned out to be great inflection points for Django as a
project and for our community. The landing of the &amp;quot;magic-removal&amp;quot; branch and the
subsequent 0.96 release was the first of these points: we released a vastly
improved Django, and our community began to grow by leaps and bounds. And of
course the release of Django 1.0 was another such moment: the maturity of
Django, and the &amp;quot;1.0&amp;quot; label proudly proclaiming our confidence, really propelled
Django forward.&lt;/p&gt;
&lt;p&gt;I'm fairly certain that 1.2 will be another such inflection point.&lt;/p&gt;
&lt;p&gt;The new features &amp;#8212; multiple database support, model validation, vastly improved
CSRF protection, improvements to the admin UI &amp;#8212; are some of the most hotly
anticipated in Django's history. These features will let our users take Django
to new levels, and I can't wait to see what y'all will be able to pull off.&lt;/p&gt;
&lt;p&gt;Over the next few weeks you'll be treated to articles discussing these new
features in depth, many written by the implementors of these features. So as to
not steal their thunder, I'll try to look at the big picture of how they all fit
together, and how they'll lay the groundwork for Django 1.3, 1.4, and beyond.&lt;/p&gt;
&lt;p&gt;Multiple database support is shaping up to be Django 1.2's killer feature. It's
been an interesting challenge adding features of this nature: there's a natural
tension between the needs of new and small-scale developers &amp;#8212; who value
simplicity and ease of use above all else &amp;#8212; and the increasing number of
large-scale Django developers &amp;#8212; who need much more control, and hence more
complexity.&lt;/p&gt;
&lt;p&gt;I think this tension between simplicity and configurability, between ease-of-use
and scale, will continue to come up. As Django matures, users will use it
to tackle tougher and tougher tasks, and we'll want Django to scale to the
challenge. At the same time, though, there'll always be many users new to
Django, and if we swamp them with complexity they'll look elsewhere, and our
community will stagnate.&lt;/p&gt;
&lt;p&gt;In Django's new multiple database support I see that we've walked the line quite
closely. I'm proud of the job we've done balancing these competing needs:
getting started with Django 1.2 is as easy as ever, but we've vastly expanded
the &amp;quot;upper end&amp;quot; of where you'll be able to take Django. It's my hope that we'll
be able to strike similar best-of-both-worlds balances.&lt;/p&gt;
&lt;p&gt;Beyond features, though, I'm most excited by the changes I'm seeing in our
development community. Over the Django 1.2 release cycle we've seen a lot of new
blood in our development community. Even better, as existing contributors' time
has waned, new developers have stepped up, and work's still getting done.&lt;/p&gt;
&lt;p&gt;Much of this new blood came to use via Google's Summer of Code 2009. The year we
accepted six projects:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Multiple database support (Alex Gaynor).&lt;/li&gt;
&lt;li&gt;HTTP and WSGI improvements (Chris Cahoon).&lt;/li&gt;
&lt;li&gt;Improved localization features (Marc Garcia).&lt;/li&gt;
&lt;li&gt;Model validation (Honza Král).&lt;/li&gt;
&lt;li&gt;Test framework additions (Kevin Kubasic).&lt;/li&gt;
&lt;li&gt;Admin UI improvements (Zain Memon).&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;The program was a smashing success: all of the projects produced good, working
code. Some has found its way into Django 1.2, and some will continue to trickle
back into trunk over the 1.3 release cycle. Many of these projects were inspired
by long-wished-for features, and the work done during the Summer of Code ended
up being what we needed to get these features over the finish line.&lt;/p&gt;
&lt;p&gt;We've also added a couple of new committers &amp;#8212; Jannis Leidel and James Tauber --
and I'd wager that we'll see a few more folks get the commit bit before the
final release.&lt;/p&gt;
&lt;p&gt;Speaking of that final release &amp;#8212; what of it?&lt;/p&gt;
&lt;p&gt;The planned release date is &lt;strong&gt;March 9, 2010&lt;/strong&gt;. We're on track for an on-time
release... but we'll never make it without your help!&lt;/p&gt;
&lt;p&gt;Every release of Django is truly the work of thousands. We need users who can
try out our beta releases in test environments and report back to us. If you
find bugs, you can report them &lt;a class="reference external" href="http://code.djangoproject.com/"&gt;on our ticket tracker&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Even better, we'd love to have your help &lt;em&gt;fixing&lt;/em&gt; bugs. Contributions on any
level &amp;#8212; developing code, writing documentation or simply triaging tickets and
helping to test proposed bugfixes &amp;#8212; are always welcome and greatly appreciated.&lt;/p&gt;
&lt;p&gt;Django's online documentation includes pointers on &lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/internals/contributing/#internals-contributing"&gt;how to contribute to
Django&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We'll also be holding development sprints for Django 1.2 at PyCon US 2010. We'll
hold four days of sprints (February 22 - 25), and we'd love to have you join us
in person in Atlanta, or virtually in IRC (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;#django-dev&lt;/span&gt;&lt;/tt&gt; on
&lt;tt class="docutils literal"&gt;irc.freenode.net&lt;/tt&gt;) or on our &lt;a class="reference external" href="http://groups.google.com/group/django-developers"&gt;mailing list&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I hope you'll enjoy the rest of the series, and I hope you'll end up as excited
about the release of Django 1.2 as I am!&lt;/p&gt;
</summary></entry></feed>
