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

<channel>
	<title>Reliably Broken &#187; django</title>
	<atom:link href="http://reliablybroken.com/b/tag/django/feed/" rel="self" type="application/rss+xml" />
	<link>http://reliablybroken.com/b</link>
	<description>It&#039;s a blog: let&#039;s do funch!</description>
	<lastBuildDate>Sat, 31 Jul 2010 01:07:08 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Django-style routing for Bottle</title>
		<link>http://reliablybroken.com/b/2010/07/django-style-routing-for-bottle/</link>
		<comments>http://reliablybroken.com/b/2010/07/django-style-routing-for-bottle/#comments</comments>
		<pubDate>Mon, 26 Jul 2010 21:57:40 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[bottle]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=510</guid>
		<description><![CDATA[Bottle provides the @route decorator to associate URL paths with view functions. This is very convenient, but if you are a Django-reject like me then you may prefer having all your URLs defined in one place, the advantage being it is easy to see at a glance all the different URLs your application will match.

Updated: [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://bottle.paws.de/">Bottle</a> provides the <a href="http://bottle.paws.de/docs/0.8/api.html#bottle.route"><code>@route</code> decorator</a> to associate URL paths with view functions. This is very convenient, but if you are a <a href="http://www.djangoproject.com/">Django</a>-reject like me then you may prefer having all your URLs defined in one place, the advantage being it is easy to see at a glance <a href="http://docs.djangoproject.com/en/1.2/topics/http/urls/#example">all the different URLs your application will match</a>.</p>

<p><em>Updated: I have re-written this post and the example to make it simpler following Marcel Hellkamp&#8217;s comments (Marcel is the primary author of Bottle). My original example was needlessly complicated.</em></p>

<p>It is possible to have <a href="http://docs.djangoproject.com/en/dev/topics/http/urls/">a Django-style urlpatterns stanza</a> with a Bottle app. Here&#8217;s how it can work:</p>

<pre><code>from bottle import route

# Assuming your *_page view functions are defined above somewhere
urlpatterns = (
    # (path, func, name)
    ('/', home_page, 'home'),
    ('/about', about_page, 'about'),
    ('/contact', contact_page, 'contact'),
)

for path, func, name in urlpatterns:
    route(path, name=name)(func)
</code></pre>

<p>Here we run through a list where each item is a triple of URL path, view function and a name for the route. For each we simply call the <code>route</code> method and then invoke it with the function object. Not as flexible as using the decorator on a function (because the <code>@route</code> decorator can take additional keyword arguments) but at least you can have all the routes in one place at the end of the module.</p>

<p>Then again if you have so many routes that you need to keep them in a pretty list you probably aren&#8217;t writing the simple application that Bottle was intended for.</p>

<p>(This was tested with Bottle&#8217;s 0.8 and 0.9-dev branches.)</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2010/07/django-style-routing-for-bottle/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>More Python features that I really like</title>
		<link>http://reliablybroken.com/b/2010/05/more-python-features-that-i-really-like/</link>
		<comments>http://reliablybroken.com/b/2010/05/more-python-features-that-i-really-like/#comments</comments>
		<pubDate>Fri, 28 May 2010 15:00:00 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Ben Dodd]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=446</guid>
		<description><![CDATA[Another thing that makes using Python pleasing is decorators. A decorator is a wrapper for a function (or method) that takes a function (or method) as an argument and returns a new function (or&#8230;) which is then bound to the name for the original function.

The newly-decorated function can then do things like checking the called [...]]]></description>
			<content:encoded><![CDATA[<p>Another thing that makes using <a href="http://www.python.org">Python</a> pleasing is decorators. <a href="http://docs.python.org/reference/compound_stmts.html#function">A decorator is a wrapper for a function</a> (or method) that takes a function (or method) as an argument and returns a new function (or&#8230;) which is then bound to the name for the original function.</p>

<p>The newly-decorated function can then do things like checking the called arguments before invoking the original un-decorated function.</p>

<p><a href="http://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.decorators.user_passes_test">Django provides decorators for authentication</a> so that you can wrap a view function with a check for client credentials before deciding whether to return the original response or a deny access.</p>

<p>In this manner Django&#8217;s authentication decorators encourage orthogonal code: the logic for displaying a view is separated from the logic for deciding whether you should be permitted to see the view&#8217;s output. By keeping them separate, it becomes simpler to re-use the authentication logic and apply it to other views.</p>

<p>Suppose you have a view that accepts <a href="http://docs.djangoproject.com/en/dev/ref/request-response/">a Django request object</a> and checks whether the user is signed in:</p>

<pre><code>def administration_page(request):
    if request.user.is_authenticated():
        return HttpResponse("Welcome, dear user.")
    else:
        return HttpResponseRedirect("/signin/")
</code></pre>

<p>With a decorator you can simplify and clarify things:</p>

<pre><code>@login_required
def administration_page(request):
    return HttpResponse("Welcome, dear user.")
</code></pre>

<p>For older versions of Python (pre 2.4) <a href="http://docs.python.org/whatsnew/2.4.html#pep-318-decorators-for-functions-and-methods">which don&#8217;t understand the <code>@</code> operator</a> one must explicitly decorate the view function like so:</p>

<pre><code>def administration_page(request):
    return HttpResponse("Welcome, dear administrator.")

administration_page = login_required(administration_page)
</code></pre>

<p>Note in the example that the original <code>administration_page</code> function is passed to the decorator. The <code>@</code> syntax in the first example makes that implicit but the two are equivalent.</p>

<p>The implementation of a decorator is interesting. It takes the function itself as an argument and returns a new function which does the actual checking. Here is how the decorator used above might do its stuff:</p>

<pre><code>def login_required(view_function):
    def decorated_function(request):
        if request.user.is_authenticated():
            return view_function(request)
        else:
            return HttpResponseRedirect("/signin/")

    return decorated_function
</code></pre>

<p><em>The actual <a href="http://code.djangoproject.com/browser/django/tags/releases/1.2.1/django/contrib/auth/decorators.py">implementation of Django&#8217;s <code>login_required</code> decorator</a> is considerably less idiotic. Python&#8217;s <a href="http://docs.python.org/library/functools.html">functools module</a> has helpers for writing well-behaved decorators.</em></p>

<p>Because functions in Python are themselves objects the decorator can accept a function reference, construct a new function that checks for authentication and then return a reference to that new function.</p>

<p>Simples!</p>

<p>(Simples gets less simples when you want to write a decorator that accepts configuration arguments because you then need either another layer of nested function definitions or a class whose instances can be called directly, but I&#8217;m going to ignore you for a bit and <em>wow is that Concorde&#8230;?</em>)</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2010/05/more-python-features-that-i-really-like/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django AdminForm objects and templates</title>
		<link>http://reliablybroken.com/b/2010/04/django-adminform-objects-and-templates/</link>
		<comments>http://reliablybroken.com/b/2010/04/django-adminform-objects-and-templates/#comments</comments>
		<pubDate>Sun, 04 Apr 2010 21:21:54 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=425</guid>
		<description><![CDATA[I can&#8217;t find documentation for the context of a Django admin template. In particular, where is the form and how does one access the fields? This post describes the template context for a generic admin model for Django 1.1.

Django uses an instance of ModelAdmin (defined in django.contrib.admin.options) to handle the request for a model object [...]]]></description>
			<content:encoded><![CDATA[<p>I can&#8217;t find documentation for the context of a Django admin template. In particular, where is the form and how does one access the fields? This post describes the template context for a generic admin model for <a href="http://code.djangoproject.com/browser/django/tags/releases/1.1">Django 1.1</a>.</p>

<p>Django uses an instance of <code>ModelAdmin</code> (defined in <a href="http://code.djangoproject.com/browser/django/tags/releases/1.1/django/contrib/admin/options.py#L175"><code>django.contrib.admin.options</code></a>) to handle the request for a model object add / change view in the admin site. <code>ModelAdmin.add_view</code> and <code>ModelAdmin.change_view</code> are responsible for populating the template context when rendering the add object and change object pages respectively.</p>

<p>Here are the keys common to add and change views:</p>

<ul>
<li><strong>title</strong>, &#8216;Add &#8216; or &#8216;Change &#8216; + your model class&#8217; <code>_meta.verbose_name</code></li>
<li><strong>adminform</strong> is an instance of <code>AdminForm</code></li>
<li><strong>is_popup</strong>, a boolean which is true when <code>_popup</code> is passed as a request parameter</li>
<li><strong>media</strong> is an instance of <a href="http://docs.djangoproject.com/en/dev/topics/forms/media/"><code>django.forms.Media</code></a></li>
<li><strong>inline_admin_formsets</strong> is a list of <a href="http://code.djangoproject.com/browser/django/tags/releases/1.1/django/contrib/admin/helpers.py#L102"><code>InlineAdminFormSet</code></a> objects</li>
<li><strong>errors</strong> is an instance of <a href="http://code.djangoproject.com/browser/django/tags/releases/1.1/django/contrib/admin/helpers.py#L198"><code>AdminErrorList</code></a></li>
<li><strong>root_path</strong> is the <code>root_path</code> attribute of the <code>AdminSite</code> object</li>
<li><strong>app_label</strong> is your model class&#8217; <code>_meta.app_label</code> attribute</li>
</ul>

<p>The way that Django renders a form in the admin view is to iterate over the <code>adminform</code> instance and then iterate over each <a href="http://code.djangoproject.com/browser/django/tags/releases/1.1/django/contrib/admin/helpers.py#L50"><code>FieldSet</code></a> which in turn yield <a href="http://code.djangoproject.com/browser/django/tags/releases/1.1/django/contrib/admin/helpers.py#L82"><code>AdminField</code></a> instances. All I want to do is layout the form fields, ignoring the fieldset groupings which may or may not be defined in the model&#8217;s <code>ModelAdmin.fieldset</code> attribute.</p>

<p>This turns out to be easy once you know how. The regular form is an attribute of the <code>adminform</code> object. So if your model has a field named &#8220;<code>king_of_pop</code>&#8221; you can refer to the form field in your template like so:</p>

<pre><code>{{ adminform.form.king_of_pop.label_tag }}: {{ adminform.form.king_of_pop }}
</code></pre>

<p>Or if you want to save your finger tips you can use the <a href="http://docs.djangoproject.com/en/dev/ref/templates/builtins/#with"><code>with</code> template tag</a>:</p>

<pre><code>{% with adminform.form as f %}
{{ f.king_of_pop.label_tag }}: {{ f.king_of_pop }}
{% endwith %}
</code></pre>

<p>Delving through the Django source while I tried to understand all of this I was struck by how <a href="http://docs.python.org/reference/datamodel.html#emulating-container-types">Python defines hook functions for iteration and accessing attributes</a>. Half of Python&#8217;s attraction is in how easy it is from the program author&#8217;s point of view to treat objects as built-in types like lists, dicts, etc.; the other half is the responsibility of the author of a Python module to encourage that same ease of use by implementing the related iteration protocols. It is harder to write a good Python module than it is to write a good Python program that uses a good module.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2010/04/django-adminform-objects-and-templates/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ModelForms good for importing too</title>
		<link>http://reliablybroken.com/b/2010/01/modelforms-good-for-importing-too/</link>
		<comments>http://reliablybroken.com/b/2010/01/modelforms-good-for-importing-too/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 20:36:25 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=395</guid>
		<description><![CDATA[If you have exported data from one database in plain text format and you want to import it to Django, you should use a ModelForm class to do a lot of the heavy lifting for you.

A suitable ModelForm for your Django model will consume each row and do the conversion of each field to an [...]]]></description>
			<content:encoded><![CDATA[<p>If you have exported data from one database in plain text format and you want to import it to <a href="http://www.djangoproject.com">Django</a>, you should use a <a href="http://docs.djangoproject.com/en/dev/topics/forms/modelforms/"><code>ModelForm</code> class</a> to do a lot of the heavy lifting for you.</p>

<p>A suitable <code>ModelForm</code> for your Django model will consume each row and do the conversion of each field to an appropriate Python type. Much simpler than explicitly converting each value yourself before creating a new model instance.</p>

<p>Suppose you have a model for an address book entry and its associated <code>ModelForm</code> (this works for Django 1.1):</p>

<pre><code># myapp/models.py
from django.db import models
from django import forms

class Contact(models.Model):
    first_name = models.CharField(max_length=100)
    second_name = models.CharField(max_length=100)
    telephone = models.CharField(max_length=50, blank=True)
    email = models.EmailField(blank=True)

class ContactForm(forms.ModelForm):
    class Meta:
        model = Contact
</code></pre>

<p>Here&#8217;s a script to run through a comma-separated list of contacts where each line looks something like &#8220;Smits, Jimmy, jimmy@example.com, 555-1234&#8243;:</p>

<pre><code>from myapp.models import ContactForm

# Map columns to fields, adjusting the order as necessary
column_map = (
    'second_name',
    'first_name',
    'email',
    'telephone',
)

for line in open('tab-separated-data.txt'):
    row = dict(zip(column_map, (field.strip() for field in line.split(','))))
    form_obj = ContactForm(row)
    try:
        form_obj.save()
    except ValueError:
        for k, v in form_obj.errors.items():
            print k, row[k], ', '.join(map(unicode, v))
</code></pre>

<p>If a line doesn&#8217;t validate the script prints the validation errors and moves to the next line. If your data has columns you want to ignore then just name them in the <code>column_map</code> &#8211; the form class will ignore extra keys in the dictionary.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2010/01/modelforms-good-for-importing-too/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Serving custom Django admin media in development</title>
		<link>http://reliablybroken.com/b/2009/12/serving-django-admin-media/</link>
		<comments>http://reliablybroken.com/b/2009/12/serving-django-admin-media/#comments</comments>
		<pubDate>Sun, 06 Dec 2009 10:00:33 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=353</guid>
		<description><![CDATA[I&#8217;ve just discovered Django&#8217;s development server always serves admin media. This is tremendously useful because it means you don&#8217;t need to configure a static serve view in your project urls.py during development.

However what bit me was I wanted to use a customised set of admin media and had configured a view for the ADMIN_MEDIA_URL path [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just discovered <a href="http://www.djangoproject.com/">Django</a>&#8217;s development server always serves admin media. This is tremendously useful because it means you don&#8217;t need to configure a static serve view in your project <code>urls.py</code> during development.</p>

<p>However what bit me was I wanted to use a customised set of admin media and had configured a view for the <code>ADMIN_MEDIA_URL</code> path and was going batty trying to work out why Django was ignoring it. It used to be that as long as you had <code>DEBUG = False</code> in <code>settings.py</code> then the development server did not try to help serve the admin media automatically.</p>

<p><a href="http://code.djangoproject.com/changeset/6075">Changeset 6075</a> added a switch to the runserver command for over-riding the admin media directory.</p>

<pre><code>python manage.py runserver --adminmedia /path/to/custom/media
</code></pre>

<p>That change was made more than two years ago. It is <a href="http://docs.djangoproject.com/en/dev/ref/django-admin/#djadminopt---adminmedia">right there in the documentation</a>. A little bit of magic that wasted fifteen minutes of my frantic schedule (except for the fact I do not have a frantic schedule).</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/12/serving-django-admin-media/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Migrating a Filemaker database to Django</title>
		<link>http://reliablybroken.com/b/2009/11/migrating-a-filemaker-database-to-django/</link>
		<comments>http://reliablybroken.com/b/2009/11/migrating-a-filemaker-database-to-django/#comments</comments>
		<pubDate>Sat, 07 Nov 2009 08:00:48 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[filemaker]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=320</guid>
		<description><![CDATA[At work we have several Filemaker Pro databases. I have been slowly working through these, converting them to Web-based applications using the Django framework. My primary motive is to replace an overly-complicated Filemaker setup running on four Macs with a single 2U rack-mounted server running Apache on FreeBSD.

At some point in the process of re-writing [...]]]></description>
			<content:encoded><![CDATA[<p>At work we have several <a href="http://www.filemaker.com/">Filemaker Pro</a> databases. I have been slowly working through these, converting them to Web-based applications using <a href="http://www.djangoproject.com/">the Django framework</a>. My primary motive is to replace an overly-complicated Filemaker setup running on four Macs with a single 2U rack-mounted server running <a href="http://httpd.apache.org/">Apache</a> on <a href="http://www.freebsd.org/">FreeBSD</a>.</p>

<p>At some point in the process of re-writing each database for use with Django I have needed to convert all the records from Filemaker to Django. There exist good <a href="http://www.python.org/">Python</a> libraries for <a href="http://code.google.com/p/pyfilemaker/">talking to Filemaker</a> but they rely on the XML Web interface, meaning that you need Filemaker running and set to publish the database on the Web while you are running an import.</p>

<p>In my experience <a href="http://www.filemaker.com/support/technologies/xml">Filemaker&#8217;s built-in XML publishing interface</a> is too slow when you want to migrate tens of thousands of records. During development of a Django-based application I find I frequently need to re-import the records as the new database schema evolves &#8211; doing this by communicating with Filemaker is tedious when you want to re-import the data several times a day.</p>

<p>So my approach has been to export the data from Filemaker as XML using <a href="http://www.filemaker.com/help/html/import_export.16.30.html#1029660">Filemaker&#8217;s FMPXMLRESULT</a> format. The Filemaker databases at work are <em>old</em> (Filemaker 5.5) and perhaps things have improved in more recent versions but Filemaker 5/6 is a very poor XML citizen. When using the FMPDSORESULT format (which has been dropped from more recent versions) it will happily generate invalid XML all over the shop. The FMPXMLRESULT format is better but even then it will emit invalid XML if the original data happens to contain funky characters.</p>

<p>So here is <a href="http://reliablybroken.com/b/wp-content/uploads/2009/11/filemaker.py">filemaker.py, a Python module for parsing an XML file produced by exporting to FMPXMLRESULT</a> format from Filemaker.</p>

<p>To use it you create a sub-class of the <code>FMPImporter</code> class and over-ride the <code>FMPImporter.import_node</code> method. This method is called for each row of data in the XML file and is passed an XML node instance for the row. You can convert that node to a more useful dictionary where keys are column names and values are the column values. You would then convert the data to your Django model object and save it.</p>

<p>A trivial example:</p>

<pre><code>import filemaker

class MyImporter(filemaker.FMPImporter):
    def import_node(self, node):
        node_dict = self.format_node(node)
        print node['RECORDID'], node_dict

importer = MyImporter(datefmt='%d/%m/%Y')
filemaker.importfile('/path/to/data.xml', importer=importer)
</code></pre>

<p>The <code>FMPImporter.format_node</code> method converts values to an appropriate Python type according to the Filemaker column type. Filemaker&#8217;s <code>DATE</code> and <code>TIME</code> types are converted to Python <a href="http://docs.python.org/library/datetime.html#date-objects"><code>datetime.date</code></a> and <a href="http://docs.python.org/library/datetime.html#time-objects"><code>datetime.time</code></a> instances respectively. <code>NUMBER</code> types are converted to Python <code>float</code> instances. Everything else is left as strings, but you can customize the conversion by over-riding the appropriate methods in your sub-class (see the source for the appropriate method names).</p>

<p>In the case of Filemaker <code>DATE</code> values you can pass the <code>datefmt</code> argument to your sub-class to specify the date format string. See Python&#8217;s <a href="http://docs.python.org/library/time.html#time.strftime">time.strptime documentation</a> for the complete list of the format specifiers.</p>

<p>The code uses <a href="http://docs.python.org/library/xml.sax.html">Python&#8217;s built-in SAX parser</a> so that it is efficent when importing huge XML files (the process uses a constant 15 megabytes for any size of data on my Mac running Python 2.5).</p>

<p>Fortunately I haven&#8217;t had to deal with Filemaker&#8217;s repeating fields so I have no idea how the code works on repeating fields. Please let me know if it works for you. Or not.</p>

<p><a href="http://reliablybroken.com/b/wp-content/uploads/2009/11/filemaker.py">Download filemaker.py</a>. This code is released under a 2-clause BSD license.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/11/migrating-a-filemaker-database-to-django/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Outputting Excel with Django</title>
		<link>http://reliablybroken.com/b/2009/09/outputting-excel-with-django/</link>
		<comments>http://reliablybroken.com/b/2009/09/outputting-excel-with-django/#comments</comments>
		<pubDate>Tue, 01 Sep 2009 20:36:14 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[excel]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=276</guid>
		<description><![CDATA[xlwt is an excellent Python module for generating Microsoft Excel documents (xlrd is its counterpart for consuming Excel documents). I use it in a Django Web application so a visitor can export her data as a spreadsheet.

Django&#8217;s documentation includes an example of how to export data in comma-separated values (CSV) format. CSV has the significant [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://pypi.python.org/pypi/xlwt"><code>xlwt</code></a> is an excellent Python module for generating <a href="http://office.microsoft.com/excel">Microsoft Excel</a> documents (<a href="http://pypi.python.org/pypi/xlrd"><code>xlrd</code> is its counterpart</a> for consuming Excel documents). I use it in a <a href="http://www.djangoproject.com/">Django</a> Web application so a visitor can export her data as a spreadsheet.</p>

<p>Django&#8217;s documentation includes an example of <a href="http://docs.djangoproject.com/en/dev/howto/outputting-csv/">how to export data in comma-separated values (CSV) format</a>. CSV has the significant advantage of being a standard Python module as well as being a relatively simple and non-vendor specific format. However there are some disadvantages to using CSV:</p>

<ol>
<li>Values can only be stored as strings or numbers.</li>
<li>Unicode text must be explicitly encoded as UTF-8.</li>
<li>Users are often unfamiliar with the <code>.csv</code> file name extension &#8211; &#8220;What the hell do I do with this damn you?&#8221;</li>
</ol>

<p>It would be unfriendly of me to expect a user to open a CSV file and then format a column of date strings as proper date values (especially when the user is almost certainly using Excel already). So I choose Excel format over CSV format.</p>

<p>Dates in Excel documents (97/2004 format) are actually stored as numbers. In order to have them appear as dates one must apply a date formatting. You do this by using <code>xlwt.easyxf</code> to create a suitable style instance and then pass that when writing the cell data.</p>

<p>A word of advice: do <em>not</em> instantiate style objects more than once! My initial approach created a new style whenever writing a date/time value. Only once I was testing with more than a few dozen rows did I discover that Excel will grow grumpy and complain about too many fonts being open when trying to display the spreadsheet. The correct approach is to have one instance for each different style and then re-use that instance for the appropriate type of value.</p>

<p>Here is an example that writes all objects of one class to a spreadsheet and sends that file to the client&#8217;s browser. You could stuff this in a Django view method.</p>

<pre><code>from datetime import datetime, date
from django.http import HttpResponse
from myproject.myapp.models import MyModel
import xlwt


book = xlwt.Workbook(encoding='utf8')
sheet = book.add_sheet('untitled')

default_style = xlwt.Style.default_style
datetime_style = xlwt.easyxf(num_format_str='dd/mm/yyyy hh:mm')
date_style = xlwt.easyxf(num_format_str='dd/mm/yyyy')

values_list = MyModel.objects.all().values_list()

for row, rowdata in enumerate(values_list):
    for col, val in enumerate(rowdata):
        if isinstance(val, datetime):
            style = datetime_style
        elif isinstance(val, date):
            style = date_style
        else:
            style = default_style

        sheet.write(row, col, val, style=style)

response = HttpResponse(mimetype='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename=example.xls'
book.save(response)
return response
</code></pre>

<p>That code works a peach with a 30,000 row / 25 column database, taking about a minute to generate a 13 megabyte file on <a href="http://support.apple.com/kb/SP45">my lowly iMac G5</a>.</p>

<p>You want to buy me <a href="http://www.apple.com/imac/">a new Intel iMac</a>, don&#8217;t you? Yes, you do.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/09/outputting-excel-with-django/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Django and time zone-aware date fields (redux)</title>
		<link>http://reliablybroken.com/b/2009/08/django-and-time-zone-aware-date-fields-redux/</link>
		<comments>http://reliablybroken.com/b/2009/08/django-and-time-zone-aware-date-fields-redux/#comments</comments>
		<pubDate>Sat, 01 Aug 2009 21:35:10 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[time zone]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=251</guid>
		<description><![CDATA[Previously on 24&#8230;

I posted a module for handling time zone-aware datetime objects, but I left out all the hassle of dealing with form input. Here is a more complete python package for Django that includes a form field sub-class that can handle a small set of datetime string formats that include a time zone offset.

Timezones [...]]]></description>
			<content:encoded><![CDATA[<p>Previously on 24&#8230;</p>

<p>I posted <a href="http://reliablybroken.com/b/2009/06/django-and-time-zone-aware-date-fields/">a module for handling time zone-aware datetime objects</a>, but I left out all the hassle of dealing with form input. Here is a more complete python package for <a href="http://www.djangoproject.com/">Django</a> that includes a form field sub-class that can handle a small set of datetime string formats that include a time zone offset.</p>

<p><a href="http://reliablybroken.com/b/wp-content/uploads/2009/08/timezones-01.tar.gz">Timezones 0.1</a></p>

<p>This code is released under Django&#8217;s BSD license.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/08/django-and-time-zone-aware-date-fields-redux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Grep template tag for Django</title>
		<link>http://reliablybroken.com/b/2009/07/grep-template-tag-for-django/</link>
		<comments>http://reliablybroken.com/b/2009/07/grep-template-tag-for-django/#comments</comments>
		<pubDate>Wed, 15 Jul 2009 17:41:51 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=231</guid>
		<description><![CDATA[Nice and easy couple of Django template tags that filter lines of text using a regular expression. I had a block of text where I wanted to remove some of the lines but not others.

You can use grep to remove any lines that do not match your pattern:

&#62;&#62;&#62; s = 'The quick brown fox'
&#62;&#62;&#62; grep(s, [...]]]></description>
			<content:encoded><![CDATA[<p>Nice and easy couple of <a href="http://docs.djangoproject.com/en/dev/ref/templates/builtins/">Django template tags</a> that filter lines of text using a regular expression. I had a block of text where I wanted to remove some of the lines but not others.</p>

<p>You can use <code>grep</code> to remove any lines that do not match your pattern:</p>

<pre><code>&gt;&gt;&gt; s = 'The quick brown fox'
&gt;&gt;&gt; grep(s, 'quick')
u'The quick brown fox'
</code></pre>

<p>And its converse <code>grepv</code> to remove any lines that do match your pattern:</p>

<pre><code>&gt;&gt;&gt; s = 'The quick brown fox'
&gt;&gt;&gt; grepv(s, 'quick')
''
&gt;&gt;&gt; s2 = s + '\nJumps over the lazy dog'
&gt;&gt;&gt; grepv(s2, 'quick')
u'Jumps over the lazy dog'
</code></pre>

<p>Stick it in a module in your Django application (<a href="http://docs.djangoproject.com/en/dev/howto/custom-template-tags/">documentation</a>), then load it up at the top of a template.</p>

<pre><code>from django import template
from django.template.defaultfilters import stringfilter
import re


register = template.Library()


@register.filter
@stringfilter
def grep(value, arg):
    """Lines that do not match the regular expression are removed."""
    pattern = re.compile(arg)
    lines = [line for line in re.split(r'[\r\n]', value) if pattern.search(line)]
    return '\n'.join(lines)


@register.filter
@stringfilter
def grepv(value, arg):
    """Lines that match the regular expression are removed."""
    pattern = re.compile(arg)
    lines = [line for line in re.split(r'[\r\n]', value) if not pattern.search(line)]
    return '\n'.join(lines)
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/07/grep-template-tag-for-django/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django and time zone-aware date fields</title>
		<link>http://reliablybroken.com/b/2009/06/django-and-time-zone-aware-date-fields/</link>
		<comments>http://reliablybroken.com/b/2009/06/django-and-time-zone-aware-date-fields/#comments</comments>
		<pubDate>Sun, 07 Jun 2009 22:34:54 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[time zone]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=168</guid>
		<description><![CDATA[Django makes it inordinately complicated to support time zone-aware dates and times because it has so far simply ignored the problem (so far being Django 1.0.2).

This is understandable given the database-agnostic nature of the Django ORM: although PostgreSQL 8.3 supports a datetime type which is time zone-aware, MySQL 5.1 does not (I have no idea [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.djangoproject.com/">Django</a> makes it inordinately complicated to support time zone-aware dates and times because it has so far simply ignored the problem (so far being <a href="http://docs.djangoproject.com/en/dev/releases/1.0.2/">Django 1.0.2</a>).</p>

<p>This is understandable given the database-agnostic nature of the Django ORM: although <a href="http://www.postgresql.org/docs/8.3/">PostgreSQL 8.3</a> supports a datetime type which is time zone-aware, <a href="http://dev.mysql.com/doc/refman/5.1/en/">MySQL 5.1 does not</a> (I have no idea what <a href="http://www.sqlite.org/">SQLite</a> does about time zones). By ignoring time zones, Django works with the lowest common denominator.</p>

<p>Given time zone support in Postgres, there is a chunk of work to write a variation of <a href="http://docs.djangoproject.com/en/dev/ref/models/fields/#datetimefield"><code>models.DateTimeField</code></a> which can handle time zone-wise datetimes. Python 2.5 does not help things &#8211; <a href="http://docs.python.org/library/datetime.html">Python&#8217;s native datetime module</a> is similarly agnostic about time zones, the standard library does not include a module for handling wise datetimes.</p>

<p>(If regular datetime instances are <em>naive</em> then datetime instances that honour time zones are <em>wise</em>.)</p>

<p>Django does make it pretty easy to <a href="http://docs.djangoproject.com/en/dev/howto/custom-model-fields/">write a custom field class</a>, which means it shouldn&#8217;t be too difficult to write a custom datetime field class that is time zone-wise. As ever it is the Django project&#8217;s regard for documentation that transforms <em>that which is possible</em> into <em>that which is practical</em>.</p>

<p>Given your backend database has a time zone-wise datetime type (i.e. PostgreSQL), what input values does one need to handle in a time zone-wise custom field class?</p>

<ul>
<li>value set to None</li>
<li>value set to a naive datetime instance</li>
<li>value set to a wise datetime instance</li>
<li>value set to a naive datetime string</li>
<li>value set to a wise datetime string</li>
</ul>

<p>Now the essence of a custom field in Django is two methods: <code>to_python</code> and <code>get_db_prep_value</code>. If the custom field defines</p>

<pre><code>__metaclass__ = models.SubfieldBase
</code></pre>

<p>then the <code>to_python</code> method will be called any time a value is assigned to the field, and we can make sure that a suitable type is returned before the model object is saved. Because Postgres <a href="http://developer.postgresql.org/pgdocs/postgres/functions-datetime.html">supports time zone-wise datetimes</a> and if we take care to return a wise datetime instance we can ignore <code>get_db_prep_value</code>.</p>

<p>When Django reads a record from the database it strips the time zone information, effectively giving your custom field a naive datetime string that belongs to the same time zone as the database connection object. (At least this seems to be true for Postgres and <a href="http://initd.org/pub/software/psycopg/">the psycopg2 adaptor</a>.) And since the database connection sets the time zone to be the same as set by <a href="http://docs.djangoproject.com/en/dev/ref/settings/#time-zone"><code>settings.TIME_ZONE</code></a> your custom class needs to treat any naive datetime strings as belonging to the time zone set with <code>settings.TIME_ZONE</code>.</p>

<p>So this leads to the important behaviour for a time zone-wise <code>DateTimeField</code> sub-class: always convert naive datetimes to the time zone set in <code>settings.TIME_ZONE</code>.</p>

<p>For convenience my custom field class, the <code>TZDateTimeField</code>, returns a sub-class of Python&#8217;s <code>datetime</code> which has an extra method that converts the datetime to the zone defined by the project&#8217;s time zone. Therefore whether the field value has been set from a naive or wise datetime instance, or a naive or wise date string you will end up with a time zone-wise value and you can get the value converted to the project&#8217;s time zone. This extra method is intended for use in a Django template.</p>

<p>What I was hoping was that the backend would store the datetime as a datetime in an arbitrary zone, potentially a different time zone from one record to the next for the same field. That behaviour would allow one to infer that one datetime value was created in this time zone while another datetime value was created in that time zone. Instead all datetime values are effectively normalized to your Django project&#8217;s time zone.</p>

<p>So here is an example of a model class that uses my time zone-aware datetime field. It ought to work just like a regular <code>DateTimeField</code> but always stores a time zone-aware datetime instance:</p>

<pre><code>from django.db import models
from timezones.fields import TZDateTimeField
from datetime import datetime


class Article(models.Model):
    pub_date = TZDateTimeField(default=datetime.now)
</code></pre>

<p>And below is my custom field definition, which has a dependency on <a href="http://pytz.sourceforge.net/">the pytz module</a> to handle all the difficult stuff. <a href="http://reliablybroken.com/b/wp-content/uploads/2009/06/timezones.zip">You can grab the complete module over here</a>, including tests in <a href="http://docs.python.org/library/doctest.html">doctest format</a>. The tests are intended to be run by Django&#8217;s <code>manage.py</code> test management command, and so one needs to add the module to <a href="http://docs.djangoproject.com/en/dev/ref/settings/#installed-apps">the list of installed apps</a>.</p>

<pre><code>"""A time zone-aware DateTime field.

When saving, naive datetime objects are assumed to belong to the local time
zone and are converted to UTC. When loading from the database the naive datetime
objects are converted to UTC.

These field types require database support. MySQL 5 will not work.
"""
from datetime import datetime, tzinfo, timedelta
from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
import pytz
import re


# 2009-06-04 12:00:00+01:00 or 2009-06-04 12:00:00 +0100
TZ_OFFSET = re.compile(r'^(.*?)\s?([-\+])(\d\d):?(\d\d)$')


class TZDatetime(datetime):
    def aslocaltimezone(self):
        """Returns the datetime in the local time zone."""
        tz = pytz.timezone(settings.TIME_ZONE)
        return self.astimezone(tz)


class TZDateTimeField(models.DateTimeField):
    """A DateTimeField that treats naive datetimes as local time zone."""
    __metaclass__ = models.SubfieldBase

    def to_python(self, value):
        """Returns a time zone-aware datetime object.

        A naive datetime is assigned the time zone from settings.TIME_ZONE.
        This should be the same as the database session time zone.
        A wise datetime is left as-is. A string with a time zone offset is
        assigned to UTC.
        """
        try:
            value = super(TZDateTimeField, self).to_python(value)
        except ValidationError:
            match = TZ_OFFSET.search(value)
            if match:
                value, op, hours, minutes = match.groups()
                value = super(TZDateTimeField, self).to_python(value)
                value = value - timedelta(hours=int(op + hours), minutes=int(op + minutes))
                value = value.replace(tzinfo=pytz.utc)
            else:
                raise

        if value is None:
            return value

        # Only force zone if the datetime has no tzinfo
        if (value.tzinfo is None) or (value.tzinfo.utcoffset(value) is None):
            value = force_tz(value, settings.TIME_ZONE)
        return TZDatetime(value.year, value.month, value.day, value.hour,
            value.minute, value.second, value.microsecond, tzinfo=value.tzinfo)


def force_tz(obj, tz):
    """Converts a datetime to the given timezone.

    The tz argument can be an instance of tzinfo or a string such as
    'Europe/London' that will be passed to pytz.timezone. Naive datetimes are
    forced to the timezone. Wise datetimes are converted.
    """
    if not isinstance(tz, tzinfo):
        tz = pytz.timezone(tz)

    if (obj.tzinfo is None) or (obj.tzinfo.utcoffset(obj) is None):
        return tz.localize(obj)
    else:
        return obj.astimezone(tz)
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/06/django-and-time-zone-aware-date-fields/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Using plists for site-specific Django settings</title>
		<link>http://reliablybroken.com/b/2009/05/using-plists-for-site-specific-django-settings/</link>
		<comments>http://reliablybroken.com/b/2009/05/using-plists-for-site-specific-django-settings/#comments</comments>
		<pubDate>Wed, 20 May 2009 22:00:51 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[plist]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=150</guid>
		<description><![CDATA[I have a Django project that I am going to deploy at several sites, but I need
to tweak the project settings slightly for each site. Specifically I need
different a EMAIL_HOST address and related settings for sending mail at each
site.

The simplest route is to customize the project settings.py as part of the
site deployment, but that will [...]]]></description>
			<content:encoded><![CDATA[<p>I have a <a href="http://www.djangoproject.com/">Django</a> project that I am going to deploy at several sites, but I need
to tweak the project settings slightly for each site. Specifically I need
different a <a href="http://docs.djangoproject.com/en/dev/ref/settings/#email-host">EMAIL_HOST address and related settings</a> for sending mail at each
site.</p>

<p>The simplest route is to customize the project settings.py as part of the
site deployment, but that will drive you insane when you deploy the wrong
custom-settings to a site.</p>

<p>Another approach is similar to that used by many for switching between settings
when moving between testing / staging / live environments: your <code>settings.py</code>
has a few lines something like</p>

<pre><code>try:
    from sitesettings import *
except ImportError:
    pass
</code></pre>

<p>so you can over-ride any setting by putting them in a <code>sitesettings.py</code> file,
and then make sure your deployment never overwrites that site-specific file.</p>

<p>In my case I want to make it easy for the site administrator to customize
the settings, but I am worried that it is too easy for someone who does not
know Python syntax to inadvertently break things by writing a <code>sitesettings.py</code>
that throws <a href="http://docs.python.org/library/exceptions.html#exceptions.SyntaxError">a <code>SyntaxError</code> exception</a>. Given the significance of
white-space in Python I feel this would be easy to get wrong.</p>

<p>So I&#8217;ve gone for storing the custom settings in Mac OS X&#8217;s <a href="http://developer.apple.com/documentation/Darwin/Reference/ManPages/man5/plist.5.html">property list
format</a>. Bless Python for it has <a href="http://docs.python.org/library/plistlib.html">the plistlib module</a> that reads
and writes the simple XML format of property lists.</p>

<p>Here&#8217;s my module that imports all properties from a plist straight into the
module&#8217;s namespace. This then makes it easy to over-ride Django&#8217;s settings
by doing</p>

<pre><code>from plistsettings import *
</code></pre>

<p>A couple bits made my lips move during the writing. The contents of <code>__all__</code>
are updated dynamically because I wanted to use this with
<code>from plistingsettings import *</code> without worrying that my module&#8217;s imports
would get clobbered by imports used in the <code>plistsettings</code> module. And working
out how to bind keys and values to the module itself is not obvious to me -
it <em>feels</em> like one ought to be able to use <code>self</code> within the scope of the
module to refer to the module itself. Except you can&#8217;t. No biggie.</p>

<pre><code># plistsettings.py
import os.path
import plistlib
import sys
from xml.parsers.expat import ExpatError


__all__ = []


PLIST_PATH = '/Library/Preferences/com.example.plist'


def read_prefs(plist_path):
    """Import settings from preference file into this module's global namespace.

    Returns a dictionary as returned by plistlib.readPlist().
    """
    try:
        if os.path.exists(plist_path):
            prefs = plistlib.readPlist(plist_path)
        else:
            return
    except ExpatError:
        return

    mod = sys.modules[__name__]
    global __all__

    for key, value in prefs.items():
        setattr(mod, key, value)
        __all__.append(key)
    return prefs

read_prefs(PLIST_PATH)
</code></pre>

<p>Now if you are the kind of Mac guy who enjoys using <code>defaults</code> you can write
out your site-specific settings from the command-line.</p>

<pre><code>defaults write /Library/Preferences/com.example EMAIL_HOST smtp.example.com
plutil -convert xml1 /Library/Preferences/com.example.plist
</code></pre>

<p>N.B. Mac OS X 10.5 <code>defaults</code> uses the binary format by default, so you need
<code>plutil</code> to convert it back to XML because <code>plistlib</code> does not handle
the binary format.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/05/using-plists-for-site-specific-django-settings/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Q and operator.or_</title>
		<link>http://reliablybroken.com/b/2009/04/q-and-operatoror_/</link>
		<comments>http://reliablybroken.com/b/2009/04/q-and-operatoror_/#comments</comments>
		<pubDate>Thu, 09 Apr 2009 18:56:12 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=123</guid>
		<description><![CDATA[I&#8217;ve finally settled on a nice syntax for OR-ing Django Q objects.

For a simple site search feature I needed to search for a term across several
fields in a model. Suppose the model looks like this:

class BlogPost(models.Model):
    title = models.CharField(max_length=100)
    body = models.TextField()
    summary = models.TextField()


And you [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve finally settled on a nice syntax for <code>OR</code>-ing <a href="http://docs.djangoproject.com/en/dev/topics/db/queries/#complex-lookups-with-q-objects">Django Q objects</a>.</p>

<p>For a simple site search feature I needed to search for a term across several
fields in a model. Suppose the model looks like this:</p>

<pre><code>class BlogPost(models.Model):
    title = models.CharField(max_length=100)
    body = models.TextField()
    summary = models.TextField()
</code></pre>

<p>And you have a view method that accepts a parameter <code>q</code> for searching across
the <code>title</code>, <code>body</code> and <code>summary</code> fields. I want to find objects that contain
the <code>q</code> phrase in any of those fields. I need to build a <a href="http://docs.djangoproject.com/en/dev/ref/models/querysets/"><code>QuerySet</code></a>
with a filter that is the equivalent of</p>

<pre><code>queryset = BlogPost.objects.filter(
    Q(title__icontains=q) | Q(body__icontains=q) | Q(summary__icontains=q)
)
</code></pre>

<p>That&#8217;s not too much of a hassle for this simple example, but in cases where
the fields you are searching are chosen dynamically, or where you just have
an awful lot of fields to search against, I think it is nicer to do it like so:</p>

<pre><code>import operator

search_fields = ('title', 'body', 'summary')
q_objects = [Q(**{field + '__icontains':q}) for field in search_fields]
queryset = BlogPost.objects.filter(reduce(operator.or_, q_objects))
</code></pre>

<p>Nice one! The list comprehension gives me a list of <code>Q</code> objects generated from
the names in <code>search_fields</code>, so it is easy to change the fields to be searched.
And using <a href="http://docs.python.org/library/functions.html#reduce"><code>reduce</code></a> and <a href="http://docs.python.org/library/operator.html"><code>operator.or_</code></a> gives me the
required <code>OR</code> filter in one line.</p>

<p>I see for Python 3 <code>reduce</code> has been <a href="http://docs.python.org/library/functools.html">moved to the <code>functools</code> module</a>.</p>

<p>This stuff never used to be that obvious to me. It kind of isn&#8217;t even now.</p>

<p>P.S. I promise I am not writing a blog engine at this time, it was just for
the example.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/04/q-and-operatoror_/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>reverse() chicken and egg problem</title>
		<link>http://reliablybroken.com/b/2009/03/reverse-chicken-and-egg-problem/</link>
		<comments>http://reliablybroken.com/b/2009/03/reverse-chicken-and-egg-problem/#comments</comments>
		<pubDate>Mon, 30 Mar 2009 14:34:07 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[urlpatterns]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=111</guid>
		<description><![CDATA[I wound up in a chicken and egg situation today using Django&#8217;s syndication
framework and the reverse helper. The problem was
that immediately after starting the development server, Django would throw a
NoReverseMatch exception on the first client visit, followed by AttributeError
on all subsequent visits.

It all started so innocently&#8230; I had wanted a set of urls for my [...]]]></description>
			<content:encoded><![CDATA[<p>I wound up in a chicken and egg situation today using <a href="http://docs.djangoproject.com/en/dev/ref/contrib/syndication/">Django&#8217;s syndication
framework</a> and the <a href="http://docs.djangoproject.com/en/dev/topics/http/urls/#reverse"><code>reverse</code></a> helper. The problem was
that immediately after starting the development server, Django would throw a
<code>NoReverseMatch</code> exception on the first client visit, followed by <code>AttributeError</code>
on all subsequent visits.</p>

<p>It all started so innocently&#8230; I had wanted a set of urls for my application
like this:</p>

<ul>
<li><a href="">http://example.com/a/</a>         # List view of arrivals</li>
<li><a href="">http://example.com/d/</a>         # List view of departures</li>
<li><a href="">http://example.com/a/feed/</a>    # Syndication feed for arrivals</li>
<li><a href="">http://example.com/d/feed/</a>    # Syndication feed for departures</li>
</ul>

<p>So I put the following in the application&#8217;s <code>urls.py</code>:</p>

<pre><code># myapp/urls.py
from django.conf.urls.defaults import *
from views import arrivals_list, departures_list
from feeds import LatestArrivals, LatestDepartures


feed_dict = {'a': LatestArrivals, 'd': LatestDepartures}


urlpatterns = patterns('',
    (r'^a/$', arrivals_list, {}, 'arrivals'),
    (r'^d/$', departures_list, {}, 'departures'),
    (r'^(?P&lt;url&gt;[ad])/feed/$', 'django.contrib.syndication.views.feed', {'feed_dict':feed_dict}),
)
</code></pre>

<p>That covers my URL wishes, and because I have named the URL patterns I
can use that name in templates with the <a href="http://docs.djangoproject.com/en/dev/ref/templates/builtins/#url"><code>{% url %} template tag</code></a>
and in Python code using the <code>reverse</code> helper.</p>

<p>So naturally the feed classes in <code>feeds.py</code> look like this:</p>

<pre><code># myapp/feeds.py
from django.contrib.syndication.feeds import Feed
from django.core.urlresolvers import reverse
from django.utils.feedgenerator import Atom1Feed
from models import Tx


class LatestArrivals(Feed):
    """Produces an Atom feed of recent arrival tickets."""
    feed_type = Atom1Feed
    title = 'Arrivals'
    link = reverse('arrivals')
    subtitle = 'Most recent arrivals'

    def items(self):
        return Tx.objects.arrivals()[:10]


class LatestDepartures(Feed):
    """Produces an Atom feed of recent departure tickets."""
    feed_type = Atom1Feed
    title = 'Departures'
    link = reverse('departures')
    subtitle = 'Most recent departures'

    def items(self):
        return Tx.objects.departures()[:10]
</code></pre>

<p>Note I used <code>reverse</code> on the link attribute of each class so that I can
define the URL in one place, the <code>urls.py</code> module, and a change there will
be reflected in the feed&#8217;s link too.</p>

<p>But this doesn&#8217;t work! When Django imports my <code>urls.py</code> module, it imports
<code>LatestDepartures</code> and <code>LatestArrivals</code>, and they in turn use <code>reverse</code> to
find the named URL patterns &#8211; except those names aren&#8217;t defined until after
<code>urlpatterns</code> has been defined in <code>urls.py</code> <em>so Django throws an exception
and never imports my <code>urls.py</code> module</em>.</p>

<p>You could work around this either by defining your syndication feeds in an
entirely different <code>urls.py</code> module. But you can also split up <code>urlpatterns</code>
within the same module and import the feed classes after their named URL
patterns have been defined.</p>

<p>Here&#8217;s the working <code>urls.py</code> module:</p>

<pre><code>from django.conf.urls.defaults import *
from views import arrivals_list, departures_list


urlpatterns = patterns('',
    (r'^a/$', arrivals_list, {}, 'arrivals'),
    (r'^d/$', departures_list, {}, 'departures'),
)


from feeds import LatestArrivals, LatestDepartures
feed_dict = {'a': LatestArrivals, 'd': LatestDepartures}


urlpatterns += patterns('',
    (r'^(?P&lt;url&gt;[ad])/feed/$', 'django.contrib.syndication.views.feed', {'feed_dict':feed_dict}),
)
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/03/reverse-chicken-and-egg-problem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using an object for Django&#8217;s ChoiceField choices</title>
		<link>http://reliablybroken.com/b/2009/03/using-an-object-for-djangos-choicefield-choices/</link>
		<comments>http://reliablybroken.com/b/2009/03/using-an-object-for-djangos-choicefield-choices/#comments</comments>
		<pubDate>Sun, 29 Mar 2009 11:07:32 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=109</guid>
		<description><![CDATA[I had another thought about per-instance choices for forms.ChoiceField.
Instead of overriding the __init__ method of your form class, you could use
an object with an __iter__ method that returns a fresh iterable each time
it is called.

from django import forms


class LetterChoices(object):
    """Return a random list of max_choices letters of the alphabet."""
    [...]]]></description>
			<content:encoded><![CDATA[<p>I had another thought about <a href="http://reliablybroken.com/b/2009/03/per-instance-choices-for-djangos-formschoicefield/">per-instance choices for <code>forms.ChoiceField</code></a>.
Instead of overriding the <code>__init__</code> method of your form class, you could use
<a href="http://python.org/doc/current/library/stdtypes.html#typeiter">an object with an <code>__iter__</code> method</a> that returns a fresh iterable each time
it is called.</p>

<pre><code>from django import forms


class LetterChoices(object):
    """Return a random list of max_choices letters of the alphabet."""
    def __init__(self, max_choices=3):
        self.max_choices = max_choices

    def __iter__(self):
        import string, random

        return iter((l, l) for l in random.sample(string.ascii_uppercase, self.max_choices))


class LetterForm(forms.Form):
    """Pick a letter from a small, random set."""
    letter = forms.ChoiceField(choices=LetterChoices())
</code></pre>

<p>I don&#8217;t know if I prefer that style to having a simple function &#8211; having to
instantiate the class seems wrong to me, I&#8217;d much rather use any callable as
the <code>choices</code> argument.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/03/using-an-object-for-djangos-choicefield-choices/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django test database runner as a context manager</title>
		<link>http://reliablybroken.com/b/2009/03/django-test-database-runner-as-a-context-manager/</link>
		<comments>http://reliablybroken.com/b/2009/03/django-test-database-runner-as-a-context-manager/#comments</comments>
		<pubDate>Sat, 28 Mar 2009 00:07:45 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[with]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=98</guid>
		<description><![CDATA[In my last post I mentioned it might be an idea to wrap up the Django test
database setup / teardown in a context manager for use with Python&#8217;s
with statement. Here&#8217;s my first stab, which seems to work.

from contextlib import contextmanager


@contextmanager
def test_db_connection():
    """A context manager for Django's test runner.

    For [...]]]></description>
			<content:encoded><![CDATA[<p>In my last post I mentioned it might be an idea to <a href="http://reliablybroken.com/b/2009/03/creating-a-django-test-database-for-unit-testing/">wrap up the Django test
database setup / teardown in a context manager</a> for use with <a href="http://docs.python.org/reference/datamodel.html#context-managers">Python&#8217;s
<code>with</code> statement</a>. Here&#8217;s my first stab, which seems to work.</p>

<pre><code>from contextlib import contextmanager


@contextmanager
def test_db_connection():
    """A context manager for Django's test runner.

    For Python 2.5 you will need
        from __future__ import with_statement
    """

    from django.conf import settings
    from django.test.utils import setup_test_environment, teardown_test_environment
    from django.db import connection

    setup_test_environment()

    settings.DEBUG = False    
    verbosity = 0
    interactive = False

    old_name = settings.DATABASE_NAME
    connection.creation.create_test_db(verbosity, autoclobber=not interactive)

    yield connection

    connection.creation.destroy_test_db(old_name, verbosity)
    teardown_test_environment()
</code></pre>

<p>All of this requires Python 2.5 or later.</p>

<p>So with that snippet you could write a test something like so:</p>

<pre><code>import unittest


class MyTestCase(unittest.TestCase):
    def test_myModelTest(self):
        with test_db_connection():
            from myproject.myapp.models import MyModel

            obj = MyModel()
            obj.save()
            self.assert_(obj.pk)
</code></pre>

<p>&#8230; and just as with Django&#8217;s <code>manage.py test</code> command the objects would be
created within the test database then destroyed when the
<code>with test_db_connection()</code> block is finished.</p>

<p>Everything&#8217;s going to be hunky dory.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/03/django-test-database-runner-as-a-context-manager/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creating a Django test database for unit testing</title>
		<link>http://reliablybroken.com/b/2009/03/creating-a-django-test-database-for-unit-testing/</link>
		<comments>http://reliablybroken.com/b/2009/03/creating-a-django-test-database-for-unit-testing/#comments</comments>
		<pubDate>Fri, 27 Mar 2009 11:02:02 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=94</guid>
		<description><![CDATA[I needed to run tests involving a Django application but without using the
manage.py test management command. So I need my own test suite that
sets up the test database and drops it after, leaving my real database untouched.

As of Django 1.0.2 the default behaviour for the test runner is the run_tests
function in django.test.simple. Here is the [...]]]></description>
			<content:encoded><![CDATA[<p>I needed to run tests involving a Django application but without using the
<code>manage.py test</code> management command. So I need my own test suite that
sets up the test database and drops it after, leaving my real database untouched.</p>

<p>As of Django 1.0.2 the default behaviour for the test runner is the <a href="http://code.djangoproject.com/browser/django/tags/releases/1.0.2/django/test/simple.py#L102"><code>run_tests</code>
function in <code>django.test.simple</code></a>. Here is the bones of that function
with the required setup and teardown calls.</p>

<pre><code>from django.conf import settings
from django.test.utils import setup_test_environment, teardown_test_environment


verbosity = 1
interactive = True

setup_test_environment()
settings.DEBUG = False    
old_name = settings.DATABASE_NAME

from django.db import connection
connection.creation.create_test_db(verbosity, autoclobber=not interactive)

# Here you run tests using the test database and with mock SMTP objects

connection.creation.destroy_test_db(old_name, verbosity)
teardown_test_environment()
</code></pre>

<p>Hmmm&#8230; Wouldn&#8217;t this be a good candidate to be wrapped up for use with
<a href="http://docs.python.org/reference/datamodel.html#context-managers">Python 2.5&#8217;s <code>with</code> statement</a>?</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/03/creating-a-django-test-database-for-unit-testing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Per-instance choices for Django&#8217;s forms.ChoiceField</title>
		<link>http://reliablybroken.com/b/2009/03/per-instance-choices-for-djangos-formschoicefield/</link>
		<comments>http://reliablybroken.com/b/2009/03/per-instance-choices-for-djangos-formschoicefield/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 08:18:44 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=65</guid>
		<description><![CDATA[I keep forgetting the details of how one customizes the choices in a forms.ChoiceField per instance. The forms.ChoiceField documentation says the required argument has to be an iterable but then moves straight to the next section.

Fortunately this was covered long ago by James Bennett when Django&#8217;s newforms module was introduced. See Getting dynamic model choices [...]]]></description>
			<content:encoded><![CDATA[<p>I keep forgetting the details of how one customizes the choices in a <code>forms.ChoiceField</code> per instance. The <a href="http://docs.djangoproject.com/en/dev/ref/forms/fields/#choicefield"><code>forms.ChoiceField</code> documentation</a> says the required argument has to be an iterable but then moves straight to the next section.</p>

<p>Fortunately this was covered long ago by <a href="http://www.b-list.org/">James Bennett</a> when Django&#8217;s newforms module was introduced. See <a href="http://www.djangosnippets.org/snippets/26/"><strong>Getting dynamic model choices in newforms</strong> on Django Snippets</a>.</p>

<p>The following form example has a field for picking a letter of the alphabet (works for <a href="http://www.djangoproject.com/">Django 1.0</a>). The choices are limited to 3 letters only, picked at random and different for each form instance:</p>

<pre><code>from django import forms


def letter_choices(max_choices=3):
    """Return a random list of max_choices letters of the alphabet."""
    import string, random

    for l in random.sample(string.ascii_uppercase, max_choices):
        yield (l, l)


class LetterForm(forms.Form):
    """Pick a letter from a small, random set."""
    letter = forms.ChoiceField(choices=letter_choices())

    def __init__(self, *args, **kwargs):
        super(LetterForm, self).__init__(*args, **kwargs)
        self.fields['letter'].choices = letter_choices()
</code></pre>

<p>So that works. The <code>LetterForm class</code> uses the helper function <code>letter_choices</code> to provide the random choices, which actually returns a generator object rather than a list or tuple of choice pairs. I am relying on Django&#8217;s base <code>ChoiceField</code> class <a href="http://code.djangoproject.com/browser/django/tags/releases/1.0.2/django/forms/fields.py#L634">calling <code>list()</code> on the choices</a> when each form is instantiated, so having <code>letter_choices</code> return a generator is hunky dory.</p>

<pre><code>&gt;&gt;&gt; f1 = LetterForm()
&gt;&gt;&gt; f1['letter']
&gt;&gt;&gt; print f1['letter']
&lt;select name="letter" id="id_letter"&gt;
&lt;option value="R"&gt;R&lt;/option&gt;
&lt;option value="N"&gt;N&lt;/option&gt;
&lt;option value="U"&gt;U&lt;/option&gt;
&lt;/select&gt;
&gt;&gt;&gt; f2 = LetterForm()
&gt;&gt;&gt; print f2['letter']
&lt;select name="letter" id="id_letter"&gt;
&lt;option value="O"&gt;O&lt;/option&gt;
&lt;option value="N"&gt;N&lt;/option&gt;
&lt;option value="T"&gt;T&lt;/option&gt;
&lt;/select&gt;
&gt;&gt;&gt; 
</code></pre>

<p>Now the only thing is&#8230; this example is not practical. Using genuinely random choices means that the valid choices on the form submitted by the user will be different to the valid choices on the form used to validate the user input on the next request, and this will likely raise a ValidationError.</p>

<p><em><strong>Django feature suggestion</strong>: allow choices to be any iterable or callable, calling it as appropriate when instantiating the field. If it is callable you could pass a function which returns an iterable at that point, which would save one having to write an <code>__init__</code> method for the form sub-class.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/03/per-instance-choices-for-djangos-formschoicefield/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>First steps with South</title>
		<link>http://reliablybroken.com/b/2009/03/first-steps-with-south/</link>
		<comments>http://reliablybroken.com/b/2009/03/first-steps-with-south/#comments</comments>
		<pubDate>Wed, 04 Mar 2009 21:50:46 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[migration]]></category>
		<category><![CDATA[south]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=52</guid>
		<description><![CDATA[My first time using a schema evolution tool for a Django project, and I like it. I chose South because it had a clear path for devolving a schema and had a database-independent API (I&#8217;ve been testing Postgres with some projects that currently use a MySQL database since we have a Trac installation that uses [...]]]></description>
			<content:encoded><![CDATA[<p>My first time using a schema evolution tool for a <a href="http://www.djangoproject.com/">Django</a> project, and I like it. I chose <a href="http://south.aeracode.org/">South</a> because it had a clear path for devolving a schema and had a database-independent API (I&#8217;ve been testing <a href="http://www.postgresql.org/">Postgres</a> with some projects that currently use a <a href="http://www.mysql.com/">MySQL</a> database since we have a <a href="http://trac.edgewall.org/wiki/DatabaseBackend">Trac installation that uses Postgres</a> anyway).</p>

<p>I have a simple application to store serial numbers and purchasing information for software. It has a <code>License</code> model, but I wanted to add a comment on each license. Following the instructions for <a href="http://south.aeracode.org/wiki/ConvertingAnApp">converting an existing app</a> on the South wiki, here&#8217;s what I did to convert my software license application.</p>

<p>First I added <code>south</code> to <code>INSTALLED_APPS</code> in <code>settings.py</code> and ran <code>manage.py syncdb</code> to install the South application tables for the first time. This was before using South to actually manage any of the evolutions.</p>

<pre><code>% ./manage.py syncdb
Syncing...
Creating table south_migrationhistory

Synced:
 &gt; django.contrib.auth
 &gt; django.contrib.contenttypes
 &gt; django.contrib.sessions
 &gt; django.contrib.sites
 &gt; django.contrib.admin
 &gt; myproject.software
 &gt; south

Not synced (use migrations):
 - 
(use ./manage.py migrate to migrate these)
</code></pre>

<p>Then I created an initial migration for my application. This gives me a migration that matches the existing database schema.</p>

<pre><code>% ./manage.py startmigration software --initial
Creating migrations directory at '/Users/david/myproject/../myproject/software/migrations'...
Creating __init__.py in '/Users/david/myproject/../myproject/software/migrations'...
Created 0001_initial.py.
</code></pre>

<p>The next step was to bring this application under South&#8217;s control. You have to pretend to apply the initial migration (because it already exists in the database), which is done using South&#8217;s <code>--fake</code> switch. I discovered a problem with my use of <code>_</code> in my <code>0001_initial.py</code> migration: the easiest fix was to import it explicitly within the migration (this fix was necessary for the second migration too).</p>

<pre><code>from south.db import db
from django.db import models
from myproject.software.models import *
from django.utils.translation import gettext_lazy as _
</code></pre>

<p>Then I was ready to bring my application under South&#8217;s control.</p>

<pre><code>% ./manage.py migrate software 0001 --fake
 - Soft matched migration 0001 to 0001_initial.
Running migrations for software:
 - Migrating forwards to 0001_initial.
 &gt; software: 0001_initial
   (faked)
</code></pre>

<p>Now I was ready to alter my model definitions and get South to do the tedious work of updating the database schema. I added a new <code>Note</code> model in the application&#8217;s <code>models.py</code> and added a new field to the existing <code>License</code> model.</p>

<pre><code>class License(models.Model):
    """A license for a software title."""
    ...
    department = models.CharField(_("Department"), max_length=100, blank=True)
    ...


class Note(models.Model):
    """A note for a license."""
    license = models.ForeignKey(License, editable=False)
    author = models.CharField(_("author"), max_length=100, editable=False)
    created = models.DateTimeField(auto_now_add=True)
    note = models.TextField(_("note text"))

    def __unicode__(self):
        return self.note

    class Meta:
        ordering = ['-created']
</code></pre>

<p>With those changes I used the <code>startmigration</code> command to generate a migration for the new model and fields.</p>

<pre><code>% ./manage.py startmigration software notes_department --model Note --add-field License.department
Created 0002_notes_department.py.
</code></pre>

<p>(Afterwards I edited the migration to import <code>_</code> as noted above.)</p>

<p>The final step was to use South to apply this migration (and any others) to the database.</p>

<pre><code>% ./manage.py migrate software 
Running migrations for software:
 - Migrating forwards to 0002_notes_department.
 &gt; software: 0002_notes_department
   = ALTER TABLE "software_license" ADD COLUMN "department" varchar(100) NOT NULL; []
   = CREATE TABLE "software_note" ("id" serial NOT NULL PRIMARY KEY, "license_id" integer NOT NULL, "author" varchar(100) NOT NULL, "created" timestamp with time zone NOT NULL, "note" text NOT NULL); []
   = ALTER TABLE "software_note" ADD CONSTRAINT "license_id_refs_id_61c4291d" FOREIGN KEY ("license_id") REFERENCES "software_license" ("id") DEFERRABLE INITIALLY DEFERRED; []
   = CREATE INDEX "software_note_license_id" ON "software_note" ("license_id"); []
 - Sending post_syncdb signal for software: ['Note']
 - Loading initial data for software.
</code></pre>

<p>Sweet!</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/03/first-steps-with-south/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using separate forms for adding and changing in Django&#8217;s admin</title>
		<link>http://reliablybroken.com/b/2009/01/using-separate-forms-for-adding-and-changing-in-djangos-admin/</link>
		<comments>http://reliablybroken.com/b/2009/01/using-separate-forms-for-adding-and-changing-in-djangos-admin/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 21:47:51 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=26</guid>
		<description><![CDATA[The Django documentation describes how to override the form class used by
the admin site when adding or editing your objects. It is easy, you just
specify a form attribute on your ModelAdmin sub-class, and point it at your
custom Form or ModelForm class.

But there is no documented method to specify one form class for creating an
object and [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://docs.djangoproject.com/">Django documentation</a> describes <a href="http://docs.djangoproject.com/en/dev/ref/contrib/admin/#form">how to override the form class used by
the admin site</a> when adding or editing your objects. It is easy, you just
specify a <code>form</code> attribute on your <code>ModelAdmin</code> sub-class, and point it at your
custom <code>Form</code> or <code>ModelForm</code> class.</p>

<p>But there is no documented method to specify one form class for creating an
object and a different form class for editing an object.</p>

<p>My solution is to override the <code>get_form</code> method on your <code>ModelAdmin</code> sub-class.
When adding an object, <code>ModelAdmin</code> will use the <code>add_view</code> method, whereas when
changing an existing object <code>ModelAdmin</code> will use the <code>change_view</code> method. You
could override the <code>add_view</code> method and specify a different form class there,
but you would need to handle the entire business of object creation, including
checking the client has permission, validating the form instance and
populating the template context. <a href="http://code.djangoproject.com/browser/django/tags/releases/1.0.2/django/contrib/auth/admin.py">Django&#8217;s auth application takes that
approach</a> for adding a new user, providing a simple username / password form
in place of the full-blown object form.</p>

<p>A simpler method is to override <code>get_form</code>. When changing an object, <code>get_form</code>
is called with the optional argument obj set to the object instance. When
adding an object the obj argument is <code>None</code>. This makes it easy to determine
when to return a different form for adding versus changing.</p>

<p>Here is an example of how to sub-class <code>ModelAdmin</code> and override the <code>get_form</code>
method to return a different form depending on whether the client is adding
a new object or changing an existing object.</p>

<pre><code># admin.py
from django.contrib import admin
from forms import MyAddForm
from models import MyModel


class MyModelAdmin(admin.ModelAdmin):
    """A ModelAdmin that uses a different form class when adding an object."""
    def get_form(self, request, obj=None, **kwargs):
        if obj is None:
            return MyAddForm
        else:
            return super(MyModelAdmin, self).get_form(request, obj, **kwargs)


admin.site.register(MyModel, MyModelAdmin)
</code></pre>

<p>Note a certain amount of hand-waving in the example where I&#8217;ve assumed that
the appropriate models and forms are defined elsewhere. The custom form class
will need to be a sub-class of <code>ModelForm</code> (or at least implement a suitable
<code>save</code> method).</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/01/using-separate-forms-for-adding-and-changing-in-djangos-admin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using SQLAlchemy with Django</title>
		<link>http://reliablybroken.com/b/2008/06/using-sqlalchemy-with-django/</link>
		<comments>http://reliablybroken.com/b/2008/06/using-sqlalchemy-with-django/#comments</comments>
		<pubDate>Mon, 16 Jun 2008 21:46:09 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[sqlalchemy]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=18</guid>
		<description><![CDATA[This post is an introduction to using SQLAlchemy and Django together
to make a simple web-based asset catalogue. The examples make use of
SQLAlchemy 0.4 and Django 0.97-pre.

Extensis Portfolio is digital asset management software that has
been available on Macinctosh (and Windows) for donkeys years.
The most expensive edition of Portfolio replaces the
native data store with an SQL back-end [...]]]></description>
			<content:encoded><![CDATA[<p>This post is an introduction to using <a href="http://www.sqlalchemy.org/">SQLAlchemy</a> and <a href="http://www.djangoproject.com/documentation/">Django</a> together
to make a simple web-based asset catalogue. The examples make use of
<a href="http://www.sqlalchemy.org/docs/04/">SQLAlchemy 0.4</a> and <a href="http://www.djangoproject.com/">Django 0.97-pre</a>.</p>

<p><a href="http://www.extensis.com/portfolio">Extensis Portfolio</a> is digital asset management software that has
been available on Macinctosh (and Windows) for donkeys years.
The most expensive edition of Portfolio replaces the
native data store with an SQL back-end (currently supported databases
are MySQL, MSSQL and Oracle). Extensis also sells <a href="http://www.extensis.com/en/products/asset_management/product_information.jsp?id=2020">NetPublish</a>, a web front-end
to a Portfolio catalogue.</p>

<p>For various reasons I decided to write a custom web front-end for
Portfolio using Django. <a href="http://reliablybroken.com/b/2008/06/choosing-sqlalchemy-over-django/">As with Farmers Wife</a>, the existing
database schema
was not well-suited to Django&#8217;s ORM. More than one table used a compound
primary key which Django does not support (there is a page <a href="http://code.djangoproject.com/wiki/MultipleColumnPrimaryKeys">discussing
how support would be implemented</a> on the Django Wiki).</p>

<h2>Defining models with SQLAlchemy</h2>

<p>The meat of the application consists of two models:</p>

<ul>
<li><strong>Items</strong> represent items in the catalogue. Each picture is an <code>Item</code>, and
has properties for things like file type, file size, path to file on
disk.</li>
<li><strong>Keywords</strong> represent keywords related to an <code>Item</code>, using a
many-to-many relationship.</li>
</ul>

<p>I defined two tables named <code>item_table</code> and <code>keyword</code> and a third that
is used to hold the many-to-many relationship:</p>

<pre><code>item_table = Table('item_table', metadata,
    Column('Record_ID', Integer(), primary_key=True, nullable=False, key="id"),
    Column(u'Filename', MSString(length=249), key="filename"),
    Column(u'Path', MSString(length=249), key="path"),
    Column(u'Created', MSDateTime(timezone=False)),
    Column(u'Last_Modified', MSDateTime(timezone=False)),
    Column(u'File_Size', MSInteger(length=11)),
    # Additional columns omitted here
)

keyword_table = Table('keyword', metadata,
    Column('Record_ID', Integer(), primary_key=True, nullable=False, key="id"),
    Column(u'Keyword', MSString(length=249), nullable=False, key="keyword"),
)

item_keyword_table = Table('Item_Keyword', metadata,
    Column(u'Item_ID', MSInteger(length=11), ForeignKey('item_table.id'), primary_key=True, nullable=False, default=PassiveDefault(u'0')),
    Column(u'Keyword_ID', MSInteger(length=11), ForeignKey('keyword.id'), primary_key=True, nullable=False, default=PassiveDefault(u'0')),
)
</code></pre>

<p>Of note here is how one can rename the table columns for use in the
table definition (roughly equivalent to the <code>db_column</code> field option in
Django). I prefer using the short name <code>id</code> for the primary key in place
of the original designer&#8217;s choice of <code>Record_ID</code>.</p>

<p>Putting <code>primary_key=True</code> on more than one column for the
<code>item_keyword_table</code> tells SQLAlchemy to use a compound primary key.
And notice the <code>ForeignKey</code> relationship uses our customized
column names for the related tables.</p>

<p>Then we need classes to associate the <code>Item</code> and <code>Keyword</code> objects with
the underlying tables,</p>

<pre><code>class Keyword(object): pass
class Item(object): pass

mapper(Keyword, keyword_table)
mapper(Item, item_table, properties=dict(
    keywords = relation(Keyword, secondary=item_keyword_table, backref="items", lazy=False, order_by=[keyword_table.c.keyword]),
))
</code></pre>

<p>The second statement above added a <code>keywords</code> property to an <code>Item</code> object
to define the many-to-many relationship with a <code>Keyword</code> object. Specifying
<code>lazy=False</code> causes the keywords related to an item to be fetched when the
item itself is loaded &#8211; the default behaviour is to leave the related
queries until the related object is accessed.</p>

<h2>Making models more Django-friendly</h2>

<p>The mapped classes for <code>Keyword</code> and <code>Item</code> behave in ways similar to a 
Django model. Any features that are missing can be easily put in place.</p>

<p>One can provide the <code>pk</code> shortcut for a model using a Python property:</p>

<pre><code>class Keyword(object):
    # Extra pk property to access primary key
    def pk(self):
        return self.id
    pk = property(pk)
</code></pre>

<p>And <code>get_absolute_url</code> is just as straight-forward:</p>

<pre><code>class Item(object):
    # Match a URL pattern like '^(?P&lt;item_id&gt;\d+)/$'
    def get_absolute_url(self):
        return reverse('catalogue_item', kwargs={'item_id':unicode(self.pk)})
</code></pre>

<p>These extra methods help SQLAlchemy model objects behave almost interchangeably
with Django model objects in your template and view methods.</p>

<p>Using the Django paginator class with SQLAlchemy <code>Query</code> objects
requires one to override a single method calculating the total number of hits:</p>

<pre><code>from django.core.paginator import ObjectPaginator as DjangoPaginator

class ObjectPaginator(DjangoPaginator):
    """SQLAlchemy compatible flavour of Django's ObjectPaginator."""
    def _get_hits(self):
        if self._hits is None:
            self._hits = self.query_set.offset(0).limit(0).count()
        return self._hits
</code></pre>

<h2>Using the models in views</h2>

<p>Unfortunately there&#8217;s no simple means for using Django&#8217;s generic
view methods (or the admin application) with SQLAlchemy&#8217;s query methods.
Django&#8217;s views rely on accessing <code>model._meta</code> from the queryset and use
an incompatible query syntax (albeit a syntax with similar intent).</p>

<p>But there&#8217;s nothing to stop you using SQLAlchemy query sets in custom
views and in the template context.</p>

<p>The following view method shows the object detail page for an <code>Item</code> object;
the primary key of the item is used in the URL and passed to the
view as <code>item_id</code>:</p>

<pre><code># Session, Item are imported from a module with the model definitions
def item(request, item_id):
    """Detail page for a Portfolio item."""
    item_id = int(item_id)
    session = Session()
    item = session.query(Item).filter_by(id=item_id).one()
    return render_to_response("catalogue/item.html", {'object':item})
</code></pre>

<p>To complete the example one ought to handle the situation where
there is not exactly one matching item. If SQLAlchemy throws
<code>sqlalchemy.exceptions.InvalidRequestError: Multiple rows returned for one()</code>
the view should in turn throw <a href="http://www.djangoproject.com/documentation/db-api/#get-kwargs">the corresponding Django exceptions</a> so
that the middleview machinery can operate as normal.</p>

<h2>The future</h2>

<p>Many parts of the API changed (or were deprected for compatibility) when
SQLAlchemy progressed from 0.3 to the current 0.4 branch, and it is
interesting how some of those changes seemed to be bringing SQLAlchemy&#8217;s ORM
approach closer to Django&#8217;s ORM. I expect more similarities to appear
on both sides in future releases.</p>

<p><a href="http://gitorious.org/projects/django-sqlalchemy/">The Django/SQLAlchemy branch</a> has the explicit goal of combining the
two without changing the Django model API, which would eliminate the
need for any of the code in this post.</p>

<p>Until that gets merged to trunk, I hope you find this useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2008/06/using-sqlalchemy-with-django/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
