Tag Archives: django

Grouping URLs in Django routing

One of the things I liked (and still like) about [Django][django] is that request routing is configured with regular expressions. You can capture positional and named parts of the request path, and the request handler will be invoked with the captured strings as positional and/or keyword arguments.

Quite often I find that the URL patterns repeat a lot of the regular expressions with minor variations for different but related view functions. For example, suppose you want CRUD-style URLs for a particular resource, you would [write an `urls.py`][urls] looking something like:

from django.conf.urls import url, patterns

urlpatterns = patterns(‘myapp.views’,
url(r’^(?P[-\w]+)/$’, ‘detail’),
url(r’^(?P[-\w]+)/edit/$’, ‘edit’),
url(r’^(?P[-\w]+)/delete/$’, ‘delete’),
)

The `detail`, `edit` and `delete` view functions (defined in `myapp.views`) all take a `slug` keyword argument, so one has to repeat that part of the regular expression for each URL.

When you have more complex routing configurations, repeating the `(?P[-\w]+)/` portion of each route can be tedious. Wouldn’t it be nice to declare that a bunch of URL patterns all start with the same capturing pattern and avoid the repetition?

It _would_ be nice.

I want to be able to write an URL pattern that defines a common base pattern that the nested URLs extend:

from django.conf.urls import url, patterns, group
from myapp.views import detail, edit, delete

urlpatterns = patterns(”,
group(r’^(?P[-\w]+)/’,
url(r’^$’, detail),
url(r’^edit/$’, edit),
url(r’^delete/$’, delete),
),
)

Of course there is no `group` function defined in Django’s `django.conf.urls` module. But if there were, it would function [like Django’s `include`][include] but act on locally declared URLs instead of a separate module’s patterns.

It happens that this is trivial to implement! Here it is:

from django.conf.urls import url, patterns, RegexURLResolver
from myapp.views import detail, edit, delete

def group(regex, *args):
return RegexURLResolver(regex, args)

urlpatterns = patterns(”,
group(r’^(?P[-\w]+)/’,
url(r’^$’, detail),
url(r’^edit/$’, edit),
url(r’^delete/$’, delete),
),
)

This way the `detail`, `edit` and `delete` view functions still get invoked with a `slug` keyword argument, but you don’t have to repeat the common part of the regular expression for every route.

There is a problem: it won’t work if you want to use a module prefix string (the first argument to `patterns(…)`). You either have to give a full module string, or use the view objects directly. So you can’t do this:

urlpatterns = patterns(‘myapp.views’,
# Doesn’t work.
group(r’^(?P[-\w]+)/’,
url(r’^$’, ‘detail’),
),
)

Personally I don’t think this is much of an issue since I prefer to use the view objects, and if you are using [class-based views][cbv] you will likely be using the view objects anyway.

I don’t know if “group” is a good name for this helper function. Other possibilities: “prefix”, “local”, “prepend”, “buxtonize”. You decide.

[django]: https://www.djangoproject.com/
[include]: https://docs.djangoproject.com/en/1.5/ref/urls/#include
[cbv]: http://ccbv.co.uk/
[urls]: https://docs.djangoproject.com/en/1.5/topics/http/urls/

Testing with Django, Haystack and Whoosh

The problem: you want to test a [Django][django] view for results of a search query, but [Haystack][haystack] will be using your real query index, built from your real database, instead of an index built from your test fixtures.

Turns out you can generalise this for any Haystack back-end by replacing the `haystack.backend` module with the simple back-end.

from myapp.models import MyModel
from django.test import TestCase
import haystack

class SearchViewTests(TestCase):
fixtures = [‘test-data.json’]

def setUp(self):
self._haystack_backend = haystack.backend
haystack.backend = haystack.load_backend(‘simple’)

def tearDown(self):
haystack.backend = self._haystack_backend

def test_search(self):
results = SearchQuerySet().all()
assert results.count() == MyModel.objects.count()

My first attempt at this made changes to the project settings [and did `HAYSTACK_WHOOSH_STORAGE = “ram”`][ram] which works but was complicated because then you have to re-build the index with the fixtures loaded, except the fixtures [don’t get loaded in `TestCase.setUpClass`][setupclass], so the choice was to load the fixtures myself or to re-index for each test. And it was specific to [the Whoosh back-end][whoosh] of course.

(This is for Django 1.4 and Haystack 1.2.7. In my actual project I get to deploy on Python 2.5. Ain’t I lucky? On a fucking PowerMac G5 running OS X Server 10.5 [for fuck sacks][bug].)

[django]: https://www.djangoproject.com/
[whoosh]: http://bitbucket.org/mchaput/whoosh
[haystack]: http://haystacksearch.org/
[setupclass]: http://docs.python.org/2/library/unittest.html#unittest.TestCase.setUpClass
[ram]: https://django-haystack.readthedocs.org/en/v1.2.7/settings.html#haystack-whoosh-storage
[bug]: http://www.youtube.com/watch?v=XZtpAxDEzl8

Optimizing queries in Haystack results

My [Adobe software updates][asu] app (which uses [Haystack][haystack] + [Django][django] to provide a search feature) has a very inefficient search results template, where for each search result the template links back to the update’s related product page.

The meat of the search results template looks something like this:

{% for result in page.object_list %}

{% endfor %}

The reverse URL lookup triggers a separate SQL query to find the related product object’s slug field for each object in the results list, and that slows down the page response significantly.

For a regular queryset you would [tell Django to fetch the related objects][select-related] in one go when populating the template context in order to avoid the extra queries, but in this case `page.object_list` is generated by Haystack. So how to tell Haystack to use `select_related()` for the queryset?

It is easy. When you register a model to be indexed with Haystack for searching, you have to define a `SearchIndex` model, and you can also override the [`read_queryset()` method that is used by Haystack to get a Django queryset][rq]:

# myapp.search_indexes.py
from haystack import indexes, site
from myapp.models import MyModel

class MyModelIndex(indexes.SearchIndex):
# Indexed fields declared here

def get_model(self):
return MyModel

def read_queryset(self):
return self.model.objects.select_related()

site.register(MyModel, MyModelIndex)

And that solved it for me. Shaves three quarters off the execution time.

PS This all pertains to Django 1.4 and Haystack 1.2.7.

PPS Also pertains to a version of my Adobe software updates page that I haven’t deployed quite yet.

[haystack]: http://haystacksearch.org/
[django]: https://www.djangoproject.com/
[asu]: http://reliablybroken.com/wavesinspace/adobe/
[select-related]: https://docs.djangoproject.com/en/1.4/ref/models/querysets/#select-related
[rq]: http://django-haystack.readthedocs.org/en/v1.2.7/searchindex_api.html#read-queryset

Caching a Django app with Nginx + FastCGI

I just spent a stupid amount of time trying to figure why [Nginx][nginx] was failing to cache my [Django][django] app responses. The Django app is running as a FastCGI backend and I have Nginx using the [`fastcgi_cache` directive][cache] to cache responses.

The answer is that [Nginx since version 0.8.44 does not cache backend responses if they have a “Set-Cookie” header][0844]. This makes perfect sense because you don’t want a response which sets a cookie to be cached for subsequent requests, but I was stupid because I had totally forgotten that my Django app was using a POST form for all responses for non-authenticated clients (due to how [Django’s CSRF middleware][csrf] does its stuff).

The solution was to change the app so that it uses the GET method on the form in question, which in this case is fine from a security point-of-view.

The moral of this story is I should pay attention to my HTTP response headers and that I am badly short-sighted both figuratively and literally. With that fixed the site has gone from 15 requests per second to ~2000 requests per second!

[nginx]: http://nginx.org/
[django]: http://www.djangoproject.com/
[0844]: http://nginx.org/en/CHANGES
[csrf]: http://docs.djangoproject.com/en/dev/ref/contrib/csrf/
[cache]: http://wiki.nginx.org/HttpFcgiModule#fastcgi_cache

Class-based views for Bottle

I’m not convinced this is actually a good idea, but I have an approach for using class-based views as handlers for a route with [Bottle][bottle].

_(If you were mad keen on [Django’s][django] shift to [class-based views][cbv] you might reckon life wouldn’t be complete with a Bottle-based application until you employ classes for views. However Bottle’s use of decorators for tying URLs to views means it is less a natural fit than the same thing in Django.)_

The problem is that you can’t just decorate the method in your class using [`bottle.route`][route] because if you use that decorator on a method in a class you are telling Bottle to use the method before it has been bound to an instance of that class.

So although I wish it did, the following example will not work:

import bottle

class ViewClass(object):
@bottle.route(“/”)
def home_view(self):
return “My home page.”

obj = ViewClass()
bottle.run()

Running that will lead to errors about not enough arguments passed to the view method of your `ViewClass` instance.

Instead you need to register the route right after the object is created. This can be done in [the class’s `__new__` method][new]:

import bottle

class ViewClass(object):
def __new__(cls, *args, **kwargs):
obj = super(ViewClass, cls).__new__(cls, *args, **kwargs)
bottle.route(“/”)(obj.home_view)
return obj

def home_view(self):
return “My home page.”

obj = ViewClass()
bottle.run()

It works. It isn’t that pretty. You could achieve exactly the same thing by explicitly passing the `obj.home_view` method to `bottle.route` _after_ the instance is created. The advantage to doing this in the `__new__` method is it will happen automatically whenever `ViewClass` is instantiated.

And if you go down this path then [you should be aware of threads][threads]. Hey! Nice threads! Also I have a cold.

[bottle]: http://bottle.paws.de/
[cbv]: http://docs.djangoproject.com/en/dev/topics/class-based-views/
[django]: http://www.djangoproject.com/
[route]: http://bottle.paws.de/docs/dev/api.html#routing
[new]: http://docs.python.org/reference/datamodel.html#object.__new__
[threads]: http://bottle.paws.de/docs/dev/tutorial.html#accessing-request-data

Running Django on Mac

These are semi-detailed steps for installing all the bits to host a [Django][django] application on [Mac OS X][macosx]. Tested on 10.5, should work perfectly on 10.6.

Use [MacPorts][macports]: relatively easy to install and the best thing is everything is contained in a directory that you can be confident won’t eff up Apple’s stuff and won’t be effed up by Apple’s stuff.

Install Xcode
————-

You need the compiler and bits that are installed with Xcode. If you can’t find your Mac install discs (Xcode is included with every new Mac but not installed) you can [download it from Apple’s developer website][xcode]. Registration is required but is free.

The current version of Xcode is easy to find, while older versions are available in the downloads section under “Developer Tools”. Xcode version 3.1.4 is the last version that will work for Mac OS X 10.5 systems.

Install MacPorts
—————-

MacPorts have a nice pkg installer. You can also build it from source.

curl -O http://distfiles.macports.org/MacPorts/MacPorts-1.9.1-10.5-Leopard.dmg
hdiutil attach MacPorts-1.9.1-10.5-Leopard.dmg
sudo installer -pkg /Volumes/MacPorts-1.9.1/MacPorts-1.9.1.pkg -target /
hdiutil detach /Volumes/MacPorts-1.9.1

If for some reason MacPorts cannot fetch updates you may need to [pull updates by hand][manualports].

Check your $PATH after installing ports to make sure `/opt/local/bin` is in there. If it isn’t your can do `export PATH=/opt/local/bin:/opt/local/sbin:${PATH}` to fix things, and even add taht line to `~/.profile` so that bash picks it up every time (assuming you haven’t switched your shell).

Install software
—————-

The `port` command is used to manipulate the MacPorts installation. Use it to build and install the various bits we need. This takes a while, especially on old PowerPC machines. Make it more exciting by adding the `–verbose` flag. Exciting!

sudo port install python26
sudo port install apache2
sudo port install mysql5-server
sudo port install mod_python26
sudo port install py26-mysql
sudo port install py26-django
sudo port install py26-south

And if you want to hook Django into a network directory then you almost certainly want to use LDAP.

sudo port install py26-ldap

Cool kids these days say use [mod_wsgi][modwsgi] instead of [mod_python][modpython] for hosting Python applications with Apache, but I am not cool (and on 20 September 2010 I couldn’t persuade mod_wsgi to build from MacPorts on a clean installation).

Configuring and starting MySQL
——————————

*UPDATED: [commenter matea][matea] pointed to [Jason Rowland’s MySQL on Mac][jason] posting that includes steps to secure a default installation, so I’ve updated this section with the appropriate steps.*

I always seem to be the only person who cares about non-English visitors… anyway, so I want to have [MySQL][mysql] use UTF8 for everything. Edit the configuration so it does. As root, create a configuration at `/opt/local/var/db/mysql5/my.cnf` with these lines:

[mysqld]
init-connect = ‘SET NAMES utf8’
character-set-server = utf8
collation-server = utf8_general_ci
skip-networking

[mysql]
default-character-set = utf8

One thing about the line `skip-networking` in the configuration file is that it means MySQL will not listen to __any__ network clients, including connections to `127.0.0.1`. Instead clients should connect to `localhost` or they should specify the path to the socket that MySQL uses for communication. If your MySQL “client” is a Django instance running on the same host then that should not be a problem.

Now initialize the database and start the server. (The use of `-w` in the second line tells launchctl to have the database daemon start at boot. If you don’t want to have MySQL running at boot use `-F` to __force__ start just this one time instead of every time.)

sudo -u mysql /opt/local/bin/mysql_install_db5
sudo launchctl load -w /Library/LaunchDaemons/org.macports.mysql5.plist

And let’s check that the server is up and configured right.

/opt/local/bin/mysql5 -e “SHOW variables LIKE ‘%char%'”

You should see a table showing that the character set for the client and server is set to utf8.

Now run the secure installation script for MySQL. This will ask you to set a password for MySQL’s root account (the administrator) and ask whether to remove the test database and anonymous user access (you should do both):

/opt/local/bin/mysql_secure_installation5

Thaz better.

Configuring Postgresql instead of MySQL
—————————————

If you want to use [Postgres][postgres] instead of MySQL then you need a couple different packages out of ports.

sudo port install postgresql84-server
sudo port install py26-psycopg2

Did you know Apple’s management tools use Postgres? Is true.

Configuring Apache to serve a Django project
——————————————–

Let’s suppose your Django project lives under `/Library/WebServer/example.com/myproj`, and the project’s settings file is `/Library/WebServer/example.com/myproj/settings.py`. Here’s how to configure Apache with mod_python to serve your project.

Create a separate site configuration for Apache in `/Library/WebServer/example.com/site.conf`.


SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE myproj.settings
PythonOption django.root /
PythonDebug On
PythonPath “[‘/Library/WebServer/example.com’] + sys.path”


Order deny,allow
Allow from all

Of course once everything is hunky dory you will go back and edit the site configuration so that `PythonDebug Off`.

And finally tell Apache to use mod_python and read the site configuration. Edit `/opt/local/apache2/conf/httpd.conf` and add a line at the end of the modules like:

LoadModule python_module modules/mod_python.so

And then a line like:

Include /Library/WebServer/example.com/site.conf

Now fire up Apache:

sudo launchctl load -w /Library/LaunchDaemons/org.macports.apache2.plist

MacPorts has a convenient shortcut for this:

sudo port load apache2

You also want to save Apache a little grief by pre-compiling the Python source files for the project:

/opt/local/bin/python2.6 -m compileall /Library/WebServer/example.com

Hope this helps.

[manualports]: http://reliablybroken.com/b/2010/03/using-macports-behind-a-firewall/
[macosx]: http://www.apple.com/macosx/
[django]: http://www.djangoproject.com
[macports]: http://www.macports.org/
[xcode]: http://developer.apple.com/technology/xcode.html
[mysql]: http://www.mysql.com
[postgres]: http://www.postgresql.org
[modwsgi]: http://docs.djangoproject.com/en/dev/howto/deployment/modwsgi/
[modpython]: http://docs.djangoproject.com/en/dev/howto/deployment/modpython/
[matea]: http://reliablybroken.com/b/2010/09/running-django-on-mac/comment-page-1/#comment-1458
[jason]: http://www.jasonrowland.com/2009/10/install-mysql5-on-snow-leopard-using-macports/

Django-style routing for Bottle

[Bottle][bottle] provides the [`@route` decorator][route] to associate URL paths with view functions. This is very convenient, but if you are a [Django][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][urlconf].

*Updated: I have re-written this post and the example to make it simpler following Marcel Hellkamp’s comments (Marcel is the primary author of Bottle). My original example was needlessly complicated.*

It is possible to have [a Django-style urlpatterns stanza][urlpatterns] with a Bottle app. Here’s how it can work:

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)

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 `route` method and then invoke it with the function object. Not as flexible as using the decorator on a function (because the `@route` decorator can take additional keyword arguments) but at least you can have all the routes in one place at the end of the module.

Then again if you have so many routes that you need to keep them in a pretty list you probably aren’t writing the simple application that Bottle was intended for.

(This was tested with Bottle’s 0.8 and 0.9-dev branches.)

[bottle]: http://bottle.paws.de/
[route]: http://bottle.paws.de/docs/0.8/api.html#bottle.route
[django]: http://www.djangoproject.com/
[urlconf]: http://docs.djangoproject.com/en/1.2/topics/http/urls/#example
[urlpatterns]: http://docs.djangoproject.com/en/dev/topics/http/urls/

More Python features that I really like

Another thing that makes using [Python][python] pleasing is decorators. [A decorator is a wrapper for a function][decorators] (or method) that takes a function (or method) as an argument and returns a new function (or…) which is then bound to the name for the original function.

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

[Django provides decorators for authentication][django] 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.

In this manner Django’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’s output. By keeping them separate, it becomes simpler to re-use the authentication logic and apply it to other views.

Suppose you have a view that accepts [a Django request object][request] and checks whether the user is signed in:

def administration_page(request):
if request.user.is_authenticated():
return HttpResponse(“Welcome, dear user.”)
else:
return HttpResponseRedirect(“/signin/”)

With a decorator you can simplify and clarify things:

@login_required
def administration_page(request):
return HttpResponse(“Welcome, dear user.”)

For older versions of Python (pre 2.4) [which don’t understand the `@` operator][syntax] one must explicitly decorate the view function like so:

def administration_page(request):
return HttpResponse(“Welcome, dear administrator.”)

administration_page = login_required(administration_page)

Note in the example that the original `administration_page` function is passed to the decorator. The `@` syntax in the first example makes that implicit but the two are equivalent.

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:

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

_The actual [implementation of Django’s `login_required` decorator][login_required] is considerably less idiotic. Python’s [functools module][functools] has helpers for writing well-behaved decorators._

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.

Simples!

(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’m going to ignore you for a bit and _wow is that Concorde…?_)

[python]: http://www.python.org
[decorators]: http://docs.python.org/reference/compound_stmts.html#function
[django]: http://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.decorators.user_passes_test
[request]: http://docs.djangoproject.com/en/dev/ref/request-response/
[syntax]: http://docs.python.org/whatsnew/2.4.html#pep-318-decorators-for-functions-and-methods
[functools]: http://docs.python.org/library/functools.html
[login_required]: http://code.djangoproject.com/browser/django/tags/releases/1.2.1/django/contrib/auth/decorators.py

Django AdminForm objects and templates

I can’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][django11].

Django uses an instance of `ModelAdmin` (defined in [`django.contrib.admin.options`][options]) to handle the request for a model object add / change view in the admin site. `ModelAdmin.add_view` and `ModelAdmin.change_view` are responsible for populating the template context when rendering the add object and change object pages respectively.

Here are the keys common to add and change views:

– **title**, ‘Add ‘ or ‘Change ‘ + your model class’ `_meta.verbose_name`
– **adminform** is an instance of `AdminForm`
– **is_popup**, a boolean which is true when `_popup` is passed as a request parameter
– **media** is an instance of [`django.forms.Media`][media]
– **inline_admin_formsets** is a list of [`InlineAdminFormSet`][inlineset] objects
– **errors** is an instance of [`AdminErrorList`][errors]
– **root_path** is the `root_path` attribute of the `AdminSite` object
– **app_label** is your model class’ `_meta.app_label` attribute

The way that Django renders a form in the admin view is to iterate over the `adminform` instance and then iterate over each [`FieldSet`][fieldset] which in turn yield [`AdminField`][adminfield] 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’s `ModelAdmin.fieldset` attribute.

This turns out to be easy once you know how. The regular form is an attribute of the `adminform` object. So if your model has a field named “`king_of_pop`” you can refer to the form field in your template like so:

{{ adminform.form.king_of_pop.label_tag }}: {{ adminform.form.king_of_pop }}

Or if you want to save your finger tips you can use the [`with` template tag][with]:

{% with adminform.form as f %}
{{ f.king_of_pop.label_tag }}: {{ f.king_of_pop }}
{% endwith %}

Delving through the Django source while I tried to understand all of this I was struck by how [Python defines hook functions for iteration and accessing attributes][hooks]. Half of Python’s attraction is in how easy it is from the program author’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.

[django11]: http://code.djangoproject.com/browser/django/tags/releases/1.1
[options]: http://code.djangoproject.com/browser/django/tags/releases/1.1/django/contrib/admin/options.py#L175
[fieldset]: http://code.djangoproject.com/browser/django/tags/releases/1.1/django/contrib/admin/helpers.py#L50
[adminfield]: http://code.djangoproject.com/browser/django/tags/releases/1.1/django/contrib/admin/helpers.py#L82
[with]: http://docs.djangoproject.com/en/dev/ref/templates/builtins/#with
[media]: http://docs.djangoproject.com/en/dev/topics/forms/media/
[inlineset]: http://code.djangoproject.com/browser/django/tags/releases/1.1/django/contrib/admin/helpers.py#L102
[errors]: http://code.djangoproject.com/browser/django/tags/releases/1.1/django/contrib/admin/helpers.py#L198
[hooks]: http://docs.python.org/reference/datamodel.html#emulating-container-types

ModelForms good for importing too

If you have exported data from one database in plain text format and you want to import it to [Django][django], you should use a [`ModelForm` class][modelform] 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 appropriate Python type. Much simpler than explicitly converting each value yourself before creating a new model instance.

Suppose you have a model for an address book entry and its associated `ModelForm` (this works for Django 1.1):

# 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

Here’s a script to run through a comma-separated list of contacts where each line looks something like “Smits, Jimmy, [email protected], 555-1234”:

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))

If a line doesn’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 `column_map` – the form class will ignore extra keys in the dictionary.

[django]: http://www.djangoproject.com
[modelform]: http://docs.djangoproject.com/en/dev/topics/forms/modelforms/