Uncategorized

Django-admin and single-item tuples

Today I learned something about Python that I did not know before: single-item tuples must have a trailing comma.

I mentioned before that certain aspects of Django leave a bad taste in my mouth, and that I was looking to other solutions as I move my language of choice for web development from PHP to Python. However, in the end I really couldn’t ignore my own advice, and I’ve been getting to know Django a little better, mostly for all the batteries included (user authentication, for example). I kinda like it. The automatic admin generator, for instance, is really nifty; at work, it lets to get the non-programmers in the other room up and running before the project is really anything more than a handful of classes.

The admin site is dynamically generated from your models, and has a concept called fieldsets: logical groupings of fields in the admin form. From the docs, here’s an example:

[code language=”python”]
class FlatPageAdmin(admin.ModelAdmin):
fieldsets = (
(None, {
‘fields’: (‘url’, ‘title’, ‘content’, ‘sites’)
}),
(‘Advanced options’, {
‘classes’: (‘collapse’,),
‘fields’: (‘enable_comments’, ‘registration_required’, ‘template_name’)
}),
)
[/code]

Basically, a tuple of tuples containing the fields and other options. Anyway, while I was creating my admin class, I kept getting a weird error:

Where the name of the field in question starts with the letter ‘x’. I was initially frustrated because the exception message isn’t very helpful, but it turns out, this isn’t so much an issue with Django as it is a gotcha in the way tuples work. My admin class contained a fieldset with only a single field, like so:

[code language=”python”]
fieldsets = (
(‘Advanced’, {
‘fields’: (‘xylophone’)
}),
)
[/code]

Okay, ‘xylophone’ is a little contrived, but my example error from earlier started with an ‘x’. Shoot me. Anyway, after RTFM, it makes perfect sense. Since my single-item tuple lacked a trailing semicolon, it wasn’t a tuple at all, but an expression. And the expression ('xylophone') returns what, class? The string xylophone. Very good! Then the interpreter was trying to iterate over a string, only there is no field that matches the first item returned: x. Hence, an error.

This is why I find actual fieldwork with a new language, framework or library to be the best way to learn it, over reading the documentation or sourcecode or anything else. Now that I’ve learned that little tidbit of information, it’s mine and I’m unlikely to make that mistake again (or if I do, I’ll recognize it instantly when I see it). No amount of documentation-reading could possibly make it stick in my head like that.

Leave a Reply