Entries in category “Django”

139 entries in this category. See also: Feed icon feed of entries in this category, list of all entry categories.

More on service layers in Django

Well, that provoked some discussion.

While there were plenty of people who agreed with the general idea of that post, there were also quite a few objections. And most of those seem to fall into two main categories: people who want some type of additional layer (and may or may not call it a “service”) as a way of managing cross-cutting complexity, and people who want it as an isolating abstraction for testing.

There’s also a third group whose objections are more about the Active Record ORM pattern, but that’s not something …

Entry published March 23, 2020. Read full entry.

Against service layers in Django

This post now has a followup.

Recently I’ve seen posts and questions pop up in a few places about a sort of “enterprise” Django style guide that’s been getting attention. There are a number of things I disagree with in that guide, but the big one, and the one people have mostly been asking about, is the recommendation to add a “service layer” to Django applications. The short version of my opinion on this is: it’s probably not what you want in Django apps.

The longer version follows below.

What is …

Entry published March 16, 2020. Read full entry.

How I’m testing in 2020

Once upon a time I wrote a bit about testing, specifically how I was organizing and testing my open-source Django apps. It’s been a while since that post, though, and the calendar has even flipped over to a new penultimate digit in the year number, so it’s worth revisiting to go over what’s changed in how I do things and what’s stayed the same. And since I do maintain a couple things that aren’t Django-related, I’d like to talk about how I test them, too.

But before I dive in, …

Entry published February 3, 2020. Read full entry.

Having some fun with Python

The other day on a Slack I hang out in, someone posted an amusing line of Python code:

port = "{port}:{port}".format(port=port)

If it’s not clear after the inevitable Swedish-chef-muppet impression has run through your mind, this string-formatting operation will replace the contents of port with a string containing two copies of whatever was in port, separated by a colon. So if port was "foo", now it will be "foo:foo".

Someone of course suggested using f-strings for a more readable version:

port = …

Entry published January 20, 2020. Read full entry.

A Python Packaging Carol

I have endeavoured in this Ghostly little book, to raise the Ghost of an Idea, which shall not put my readers out of humour with themselves, with each other, with the season, or with me. May it haunt their houses pleasantly, and no one wish to lay it.

Every year around Christmas, I make a point of re-reading Charles Dickens’ A Christmas Carol. If you’ve only ever been exposed to the story through adaptations into other media, I highly recommend getting a copy of Dickens’ original text (it’s public domain …

Entry published January 5, 2020. Read full entry.

Contributing to classiness (in Django)

A couple weeks ago I ran a poll on Twitter asking people whether they’d ever used, or considered using, the contribute_to_class() method to write something that attaches to or hooks into a Django ORM model class, and if so what their thoughts were. There was also a “don’t know what that is” option, which won by a large margin, and I promised I’d provide an explanation.

Unfortunately, that was around the time I suffered a kitchen accident which left me without full use of my left hand for a bit. Full …

Entry published March 4, 2019. Read full entry.

Truths programmers should know about case

A couple weeks ago I gave a talk about usernames at North Bay Python. The content came mostly from things I’ve learned in roughly 12 years of maintaining django-registration, which has taught me more than I ever wanted to know about how complex even “simple” things can be.

I mentioned toward the beginning of the talk, though, that it wasn’t going to be one of those “falsehoods programmers believe about X” things. If you’re not familiar with those, you can just Google for “falsehoods programmers believe” and get …

Entry published November 26, 2018. Read full entry.

Core no more

If you’re not the sort of person who closely follows the internals of Django’s development, you might not know there’s a draft proposal to drastically change the project’s governance. It’s been getting discussion on GitHub and mailing lists, but I want to take some time today to walk through and explain what this proposal does and what problems it’s trying to solve. So. Let’s dive in.

What’s wrong with Django?

Django the web framework is doing pretty well. It’s a stable, popular piece of software. Django the open-source project is OK right …

Entry published November 20, 2018. Read full entry.

django-registration 3.0

Today I’m pleased to announce the release of django-registration 3.0. This is a pretty big update, and one that’s been coming for a while, so I want to take a moment to go briefly through the changes (if you want the full version, you can check out the upgrade guide in the documentation).

This also marks the retirement of the 2.x release series of django-registration; 2.5.2 is on PyPI, and I intend for it to be the last 2.x release. The 2.x branch still exists in the repository, but I don’t …

Entry published September 4, 2018. Read full entry.

Checking if you’re pwned (with Django)

Back in March I announced the release of a couple security-related projects for Django, one that implements the Referrer-Policy header, and one that uses the Pwned Passwords database of Have I Been Pwned to check users’ passwords.

Today I’ve bumped the version and rolled a new release of pwned-passwords-django; if you’re reading this, version 1.2 is on the Python Package Index, and is only a pip install away. And, of course, there’s full documentation available on how to use it.

(technically, 1.2.1 is now the version on PyPI, …

Entry published June 18, 2018. Read full entry.

For hire

Update: I am (as of August 2018) once again gainfully employed.

Since a slightly-wider circle of people know this now, it’s time to just go public with the news: my last day at now-former employer was toward the end of January. At the time I told a few friends, but wasn’t in a huge rush to find something else immediately; I’d been getting ready to depart for a little while, and there were some things (a bit of travel, catching up on some open-source projects, and a bunch of writing) …

Entry published April 11, 2018. Read full entry.

Testing Django applications in 2018

I spend a lot of time writing Django applications. At each of my last three jobs I worked with Django, and I’m the primary maintainer of quite a few open-source Django applications. Which means I’ve written a lot of tests for code that uses Django. And although Django provides a lot of useful tools for testing, there are areas where it doesn’t prescribe or even suggest how you should do things, and over the years I’ve found myself going back and forth on different approaches and patterns. Judging from …

Entry published April 2, 2018. Read full entry.

Making mistakes

A couple weeks ago when I was writing what became pwned-passwords-django, I tweeted about a weird issue I was seeing when running the tests for part of it. As it turned out, I’d overlooked something important, and the fix ended up being a one-line change. But that kicked off a little side discussion about the importance of being open about these kinds of “trivial” mistakes; it’s easy for newer or less-confident programmers to do something like that and start feeling stupid, unqualified and all sorts of other …

Entry published March 20, 2018. Read full entry.

Two new projects

Django and security are two of my favorite topics, and I think they go pretty well together. I’ve given a number of conference talks and tutorials on the theme of Django and security, and I’m one of the people on the receiving end of Django’s security-reporting email address. But although I spend a lot of time thinking about security, and trying to improve the state of the world through code, and occasionally ranting on various forms of social media, I don’t spend a lot of time writing about it here.

So …

Entry published March 6, 2018. Read full entry.

On Django’s longevity

Django is about to be a teenager.”

I don’t remember exactly who said that, but it came up in a discussion of potential followup events to 2015’s “Django Birthday”, held in Lawrence, Kansas, to celebrate the tenth anniversary of Django’s initial public release. There might still be some parties to throw — maybe a Django sweet sixteen — but regardless of what the future holds, the summer of 2018 will mark thirteen years since the first public release, and Django will officially be a teenager.

Most pieces of software don’t make …

Entry published February 22, 2018. Read full entry.

Let’s talk about usernames

A few weeks ago I released django-registration 2.4.1. The 2.4 series is the last in the django-registration 2.x line, and from here on out it’ll only get bugfixes. The master branch is now prepping for 3.0, which will remove a lot of the deprecated cruft that’s accumulated over the past decade of maintaining it, and try to focus on best practices for modern Django applications.

I’ll write more about that sometime soon, but right now I want to spend a little bit of time talking about a deceptively hard problem django-registration …

Entry published February 11, 2018. Read full entry.

On degrees

Lately there’s been a recurring discussion on various social-media outlets about the relevance of academic degrees to a career in programming. Specifically: is a degree in computer science (or some other field perceived as related) a necessity for a career as a programmer? If not, is it still a good idea to have one?

I’ve jumped into a few such threads on Twitter, but I have complex thoughts on the topic, and 140-character or (now) 280-character chunks of commentary don’t really work for that. Luckily, I have a blog and it …

Entry published January 8, 2018. Read full entry.

Let’s talk about testing Django apps

For quite a while now, I’ve maintained several open-source Django applications. And with Django 1.11 on the horizon, it’s time for me to go through and make any changes and clean out their issue queues while I’m at it, so I can roll new officially-compatible releases. When I’m doing this, I always like to try to evaluate the current state of the art and see if I can switch over to better ways of doing things, since Django gets a new features with every release and people in the …

Entry published April 3, 2017. Read full entry.

How to break Python

Edited March 2019: updated Python 3.8 section.

Edited December 2018: added sections for Python 3.7 and upcoming 3.8, updated Python 3.6 section since Python 3.6 has been released, and updated Python 3.3 section since 3.3 has reached end-of-life.

Don’t worry, this isn’t another piece about Python 3. I’m fully in favor of Python 3, and on record as to why. And if you’re still not convinced, I suggest this thoroughly comprehensive article on the topic, which goes over not just the bits people get angry about but also the frankly …

Entry published November 28, 2016. Read full entry.

On Python 3, again

A while back, Brett Cannon went into some detail on why Python 3 happened (that is, why it was backwards-incompatible with Python 2 and why it was backwards-incompatible in the particular ways it was). Python 3 has been pretty controversial, with people I respect chiming in on both sides of the good idea/bad idea debate. And the transition (which Brett has also taken a recent look at) has indeed been slow, but that at least was fully expected — at the time, I remember announcements coming from the Python …

Entry published June 10, 2016. Read full entry.

A real Python “wat”

A few weeks ago I went through and explained the various items in a list of “Python wats” — behaviors of Python which seemingly made no sense. Calling them “wats” is a bit of a stretch in most cases, though, because most of them were simply consequences of fairly reasonable design decisions in how Python or its standard libraries work, but presented in ways which obscured what was actually going on.

Lest I be accused of defending Python too much there, I’d like to point out an absolutely genuine “wat” moment …

Entry published November 15, 2015. Read full entry.

django-registration updates

Since announcing its resurrection a couple weeks ago, I’ve been working on django-registration pretty much continuously. There are over 30 commits since that last post, and I think it’s finally getting close to release quality; what’s left at this point is, I think, mostly stylistic cleanups and editing and pushing some more documentation.

There are a couple big highlights from the past few weeks’ work, and I’d like to take a moment to go over those in a shameless attempt to build up hype and excitement for the forthcoming release.

No more …

Entry published September 6, 2015. Read full entry.


I mentioned a couple weeks ago that lately I’ve been in the process of providing updated releases for all the various open-source projects I maintain, and specifically mentioned a desire to resurrect django-registration which, once upon a time, was the most popular thing I’d ever written. Over the past week I’ve been focusing more heavily on that, and now it’s time to start talking about a release.

Ancient history

I’ve always felt pretty strongly that Django’s killer feature is its concept of an application; the ability to wrap up a chunk of …

Entry published August 13, 2015. Read full entry.

A couple quick tips

As noted the other day, I’ve spent the last little while working to freshen up various bits of open-source code I maintain, in order to make sure all of them have at least one recent release. Along the way I’ve picked up a few little tips and tricks; some of them may be old hat to you if you’ve been lucky enough to be working with fairly modern Django and Python versions for a while, but I think they’re still worth sharing. Today I’d like to dive into …

Entry published July 22, 2015. Read full entry.

News and such

First things first: though I announced this sort of quietly at the time, I should probably announce it publicly as well: after four years as part of the MDN development team, my final day at Mozilla was early last month. There are some parallels to the last time I moved on, so I’ll link to that in lieu of writing it all over again. For the moment I’m enjoying a summer vacation, but I’m at the stage now of starting to talk to folks about my next career move, …

Entry published July 20, 2015. Read full entry.


Reminder for people who try and think it’s a bug: Persona, on this site, is for me to be able to log in and post entries. As such, you will not be able to log in to this site, since you don’t have an account and can’t create one. This isn’t a bug, it’s intended functionality — site owners can control whether accounts can be created, and by whom.

So, last week I mentioned in passing that my next project for this site would be implementing Persona for authentication. Since I …

Entry published September 5, 2013. Read full entry.

Catching up

For a while now I’ve been pretty embarrassed by this site. Not by the visual design, or the functionality (though some bits have been lost along the way, for reasons that will become obvious in a moment), but by the fact that it was old. As in, over five years old. It was running on a bunch of ancient code that I’d written a long, long time ago, on an ancient Subversion checkout of Django — for the historians in the audience, it was pre-queryset-refactor — and was, frankly, …

Entry published August 26, 2013. Read full entry.

A stateful problem

Update in June 2019: This old post is getting some traffic, so I should point out that the former django.contrib.localflavor is now distributed as a separate package, rather than bundled into Django itself. Also, please note the date on this post, and the fact that it discusses Django 1.3; as I write this edit, it is nine years later and the current release of Django is 2.2.

So, this week we dropped some security updates, which you should definitely check out if you haven’t seen them yet.

We also …

Entry published December 24, 2010. Read full entry.


Step 1: pip install django-funserver

Step 2: Add “funserver” to your INSTALLED_APPS.

Step 3: Run manage.py funserver.

For best results, don’t do this on a real server.

Code is here, for those interested.

Entry published November 1, 2010. Read full entry.


So, life has been eventful lately. There was DjangoCon, which was awesome even though I came away deeply unhappy with how my talk turned out; due to a lot of hectic things going on, it fell far below the standard I usually like to enforce for myself. I’ve got a couple things cooking for PyCon, though, which will hopefully make up for it. Things are starting to ramp up for the Django 1.2 development cycle, which is looking to be chock full of awesomeness. There’s quite a lot of interestingness …

Entry published October 14, 2009. Read full entry.

Let’s talk about WSGI

Recently Armin Ronacher (whose blog you should be reading if you do anything at all involving Python and the web) has published a couple of good articles poking at the current state of WSGI, the standard interface for Python web applications. Some of his comments dovetail nicely into concerns I’ve been trying to put into words for a while now, so I’m glad he’s posting on the subject and providing some context.

In short, I’ve come to have some rather severe misgivings about WSGI — both as currently constituted …

Entry published August 10, 2009. Read full entry.

On “magic”, once again

So it seems Giles Bowkett is upset about use of the word “magic”. I’m happy to agree with the general consensus from various fora that the specific article he’s complaining about is, well, pretty much content-free. I could read that post over and over and still have no idea what actual things the author liked about Django or didn’t like about Rails. But I’ve pretty much learned to ignore content-free hype, and that’s what I did in that case.

I’m also quite happy to grant that not all programming languages do …

Entry published July 23, 2009. Read full entry.

An update on the book

So, the repository for the second edition of Practical Django Projects is not yet done, but due to the general clamor I’m opening up public access; you can browse it, or check out a copy of the code, from its page on Bitbucket. You’ll probably want to have a look over the README file displayed on that page, since it provides helpful information on how the repository works.

Right now the first three chapters’ worth of code (covering the first project in the book — a very simple content-management system) …

Entry published July 7, 2009. Read full entry.

A fun little bug

About two months ago, I quietly wrote and released a little Django application which generates cross-domain policy files for Flash (if you’ve never encountered this aspect of Flash, here’s an introductory article on how it works). I’ve done a bit of hacking on it in my spare time, and I’m pretty happy with it as an example of a simple, tightly-focused application; sometime soon I hope to write a bit more about the development process behind it, because it provides a useful real-world guide to some of the abstract …

Entry published June 26, 2009. Read full entry.

Second edition

So just after lunch today a box arrived, containing copies of the second edition of Practical Django Projects, which went through final editing about a month ago (Apress tends to be pretty quick at getting the book printed and shipping). Since I assume that means other people will be getting copies of the book soon, I’d like to cover a couple important bits of information.

First of all, the second edition (as the cover proudly declares) covers Django 1.1. Which hasn’t yet released. There are three actual bugs still open …

Entry published June 23, 2009. Read full entry.

PyCon ORM panel liveblog

I’m sitting about five rows back in the ballroom at the Hyatt, waiting for the ORM panel to begin.

Panel’s starting. Moderator Alex Gaynor introduces himself and panelists:

First question: brief history of your ORM

SQLALchemy: wanted to do a CMS, but never ended up writing it. Had idea for a modular library to talk to databases, different bits you could use or not use — connection pooling, SQL expressions, ORM — as you liked. Background was from previous …

Entry published March 28, 2009. Read full entry.

Django 2.0

So apparently some folks doing business as “Vyper Logix Corp” are peddling a thing they call “Django 2.0”. I’m not going to link it here since they don’t deserve the Google bump, but if you’re interested you can follow the link in Jannis’ tweet where he mentioned it. In fact, with any luck my Google juice will pop this article up above them.

Django 2.0” is, apparently, built on the Django 0.96.2 codebase, which is rather interesting since that means it could be missing:

Entry published January 18, 2009. Read full entry.

Second editions galore

Adrian announced today that he’s working on revising The Definitive Guide to Django to produce a second edition that covers Django 1.0, which is awesome news for anyone who’s used the book as a guide to learning Django.

In the same vein, I’d like to announce something that’s been unofficially mentioned a couple times but never fully clarified: I’m busy working on the second edition of Practical Django Projects, which will also cover Django 1.0 (and maybe a feature or two from Django 1.1, depending on how the writing schedule …

Entry published January 9, 2009. Read full entry.

Users and the admin

So, for as long as I can remember the single most-frequently-asked question about the Django admin has been some variation of “how do I set a foreign key to User to automatically be filled in with request.user?” And for a while the answer was that you couldn’t do that, really; it was and still is easy to do with a custom form in your own view, but up until a few months back it wasn’t really something you could do in the admin. Now, as of the merge of …

Entry published December 24, 2008. Read full entry.

Generic inlines and Django history

The other day at work I stumbled across my first opportunity to use a relatively-new feature in the Django admin, one which turned what had looked like it would be a fairly nasty task into, basically, a five-minute job (plus staging, testing and deployment, of course, but that happens no matter how long it takes to develop the code). I’ll get to the specifics in a minute, but first I want to give a little bit of background on what, exactly, I was working on, since it’s sort of a …

Entry published December 4, 2008. Read full entry.

Another take on content negotiation

Today my co-worker Daniel posted a class which performs content negotiation for Django views, allowing you to write a single view which returns any of several types of responses (e.g., HTML, JSON, XML) according to the incoming HTTP Accept header. While it’s certainly cool, he notes a couple of issues with it (including the redundancy it introduces in URL configuration).

So let’s see if we can’t come up with a way to work around this.

Holiday decorations

It seems that the best way to approach this is to …

Entry published November 29, 2008. Read full entry.

Writing custom management commands

The other night in the #django-dev IRC channel, Russ, Eric and I were talking about custom management commands for certain types of common but tedious tasks; Eric was discussing the possibility of a command for automatically generating a tests module in a Django application, since he’s our resident unit-testing freak, and I started toying with the idea of one to generate basic admin declarations for the models in an application.

So I sat down and spent a few minutes writing the code. I haven’t decided yet whether I want to …

Entry published November 14, 2008. Read full entry.

So you want a dynamic form

So I havent really been doing much writing lately. That’s mostly a consequence of the fact that:

  1. Django 1.0 was released, and meeting the schedule for that took up an enormous amount of time.
  2. After that, there was DjangoCon.
  3. Oh, and there are all sorts of things in my life, including a book, a gigantic codebase and dozens of sites, which all need to be updated. Our entire team here in Lawrence has been running short on sleep for a good long while now.

Anyway, I’m going to force myself to break out of …

Entry published November 9, 2008. Read full entry.


I’m sitting here in Building 40 at Google, waiting for this morning’s first DjangoCon keynote to start, and getting ready for the Django technical design panel which comes immediately afterward. Naturally, I’m taking advantage of the down time (and Google’s bandwidth) to upload my slides from yesterday’s talk. If you’ve seen/read the slides from the version of this talk I gave at PyCon, I can tell you that there are now 40% more slides and they’re all new material.

And, of course, the whole deck of slides is CC-licensed, …

Entry published September 7, 2008. Read full entry.

Media and performance

Ever since last September when I moved this site off the shared-hosting account which had been handling it from its initial launch, I’ve been using separate services to handle static files — “media” in common Django parlance — instead of using the same web server instance, or a separate instance running on the same physical server as the rest of the site. Specifically, I’m using Amazon S3.

When I first explained this a few months ago, I got a bit of pushback and a few questions, both in comments …

Entry published June 23, 2008. Read full entry.

Let’s talk about documentation

One of the most active threads on reddit’s programming section right now discusses things people look for when reviewing someone else’s code; the article being discussed treats this as a great interview question and points to things like algorithm choices and object-oriented design as good responses. While these are important considerations, I’ve found I tend to make snap judgments long before I get to that level of analysis, and they’re almost always based on one key factor: documentation.

Of course, I have the luxury of mostly reviewing Python code, and Python …

Entry published June 21, 2008. Read full entry.

Fun with queryset-refactor

Mixed in with my recent redesign and server move, I’ve taken the opportunity to update the Django trunk snapshot this site runs on; generally I snapshot a week or two after a big change, once I’ve had time to see any major bugs shake out and update the various applications I use. This time around the recent big change was the queryset-refactor branch landing in trunk. Most people have been focusing obsessively on one single feature QSRF reintroduced, but that’s a bit of a shame because it brought tons …

Entry published June 19, 2008. Read full entry.

Kick me

On a recent plane ride, I was watching an episode of The West Wing which had flashbacks to the original campaign which set up the Presidency on which the show is based. There’s a scene in that episode where Abbey Bartlet — the eventual First Lady on the show — is talking to some of her husband’s campaign staffers about whether her husband is ready to really run the campaign and be President. The dialogue is classic:

JOSH: Well, is he going to be ready?
ABBEY: You bet your …

Entry published June 7, 2008. Read full entry.

django-registration 0.5

Just a quick note: I’ve bumped django-registration to version 0.5. New in this version are Italian and Serbian translations, registration at the Cheese Shop (so you can now do easy_install django-registration) and a few bugfixes.

Notes you might care about:

Also: I’m considering taking my own advice (from …

Entry published June 5, 2008. Read full entry.

Book notes

A few notes about the book:

Entry published June 3, 2008. Read full entry.

And that’s a wrap.

I just finished reviewing and annotating the index for the book, and sent it back. And with that, I believe it’s finally done; soon it’ll be in the hands of the printer, and sometime hopefully next month you’ll be able to visit your local bookstore and pick up a copy.

My immediate plans include flying back east tomorrow to watch a couple of dear friends get married, and hopefully spending the next few days without interacting with any computers in any way.

After that… I’ve got a lot of things to …

Entry published May 28, 2008. Read full entry.

More slides

I gave a quick talk at the Django open session last night, and I’ll be giving it again here in a few minutes as a proper lightning talk, briefly walking through the process of some of the database-backed journalism projects we do at the Journal-World (specifically this feature on crime reports at the local university campus).

Slides are already online. If you’re at PyCon and want to hear the talk, come to the ballroom.

Entry published March 16, 2008. Read full entry.


I just finished my talk, which apparently included a bonus live transcript on IRC by Justin Lilly, and I think it went pretty well considering how much ground it had to cover and how nervous I was up until the moment when I started talking.

If you aren’t at PyCon, or if you are but didn’t come to the talk, or if you just want to download them and mash them up, my slides are online:

Since it includes several CC-licensed photos, and since I’m a fan of …

Entry published March 15, 2008. Read full entry.

Managers versus class methods

In the triumphant return of “James answers questions from the django-users list”, today I’d like to take a few moments to talk something that’s recently become something of a hot topic, spawning not one but two threads, as well as a couple off-list email discussions: what, exactly, is appropriate to put into a method on a custom manager as opposed to, say, a class method, and when and how can you tell?

This is a somewhat tricky question to answer, since there’s a substantial grey area where personal preference will be …

Entry published February 25, 2008. Read full entry.

On “conceptual integrity”

Mark Ramm has a nice post this morning talking about Adam Gomaa’s discussion of “conceptual integrity” in Python web frameworks; I think it’s worth a read.

The key point Mark touches on is good documentation: ensuring that people see and understand the overarching structure of the framework is, ultimately, the key to helping people understand how it can help them get their work done. In the case of Django there is an official “overview” document, but it’s really not as good as it could be; it’s basically a whirlwind tour …

Entry published February 11, 2008. Read full entry.


Between normal work, working on the book, working on my upcoming PyCon talk and working on a couple little things on the side, I haven’t had much time for blogging lately, especially about Django. But I’ve built up a collection of little things that need to get posted, so I’m just going to start dumping them out here and then get back to not having any free time :)

A django-registration update

I’ve bumped django-registration up to version 0.4p2; the new package doesn’t add any new features, but it does …

Entry published February 10, 2008. Read full entry.

Media moves

As of sometime this weekend when the DNS change propagated, all static/media files for this site migrated over to Amazon’s S3 storage service; when I relaunched back in September, media was coming off a Joyent BingoDisk account. While a change in media serving technology really isn’t all that sexy or exciting compared to some aspects of web development (or as popular as writing about whatever Microsoft is doing today), I’d like to take a moment to talk about this move, why I decided to go with S3, and point …

Entry published February 7, 2008. Read full entry.

Web frameworks and web hosts

Today John Gruber linked to a post on the official Dreamhost blog lamenting the state of web-framework deployment on consumer-level shared hosting; while the post itself is largely concerned with Ruby on Rails, the current state of deploying popular (non-PHP-based) web frameworks on hosts like Dreamhost is, well, abysmal. A search for “dreamhost” in the archives of the django-users mailing list turns up nearly five hundred results, many of them people struggling to get Django working, and I imagine that similar searches of list archives for other frameworks …

Entry published January 10, 2008. Read full entry.

The why and wherefore

So, let me straighten a few things out.

First off, this is my personal blog. What you see here is me speaking my own personal mind, and I neither represent nor want to represent anything larger: not Django, not Python web development, not my employer, not anything except me and whatever I feel like writing about. This is an important point to keep in mind, because I don’t have any claim to represent anything else:

Entry published December 31, 2007. Read full entry.

Speaking and writing

First off, if you’re going to PyCon (Chicago, March 14-16), make some room on your schedule; there are several interesting talks on Django scheduled, including one by yours truly.

The description of my talk on the PyCon site is somewhat pithy on account of space restrictions, but conveys the general idea of what I’ll be talking about; flexible, reusable Django applications are one of my pet topics, and I’ll be covering some techniques and best practices picked up from a couple years of real-world work with and on Django. It probably …

Entry published December 12, 2007. Read full entry.

Requiring HTTP methods

Just a quick tip today: someone on IRC tonight was asking for an easy way to write a Django view which restricts itself to only allowing a specific HTTP method or methods. For example, a web-based API might want to only allow POST to specific views.

This is actually pretty easy to do with a set of decorators built in to Django, in the module django.views.decorators.http. Specifically, the fix for ticket #703 added three useful things to that module:

Entry published December 11, 2007. Read full entry.

A couple updates

Today marks two releases, both numbered 0.4, of django-registration and template_utils.

The new release of django-registration is largely a matter of policy; there’s no new functionality or features, but there is one backwards-incompatible change: the validation of passwords (verifying that the same password is entered in both fields) has been moved to the clean() method of RegistrationForm, which means that the error message from a password mismatch is now accessed via form.non_field_errors() instead of form.errors[‘password2’]. It’s a relatively easy change to make in your templates, but because …

Entry published December 9, 2007. Read full entry.

The magic of template tags

Over the last couple days I’ve spent some time discussing the word “magic” and exploring just what it really means, with an emphasis on the fact that a lot of “magic” in programming — though initially counterintuitive and not at all what you’d expect to have happen (and it’s precisely this reason which usualy makes “magic” a bad idea) — boils down to applications of fairly simple principles. As a real-world demonstration of that, yesterday we saw how to build a Python module object dynamically and make it work …

Entry published December 4, 2007. Read full entry.

Making magic

In yesterday’s article I spent a fair amount of time talking about the word “magic”, specifically in the context of Clarke’s Third Law, which states that

Any sufficiently advanced technology is indistinguishable from magic.

A big part of what I was getting at was that a lot of things which seem to be explicable only by appealing to “magic” are really just cases of technology — sometimes extremely simple technology — being used in a complex way. Or, to borrow an excellent turn of phrase from Terry Pratchett, “ninety percent of most …

Entry published December 3, 2007. Read full entry.

Clarke’s Third Law

Every so often, a TV producer who wants to get ratings will air a “documentary” about some wonder of the ancient world. Say, the great pyramids at Giza. The formula for this “documentary” is pretty simple: you get a bunch of people from modern, industrialized nations to go crawl over these huge ancient monuments in Egypt and speculate on how those ancient Egyptians managed to build them. And, inevitably, a lot of these people will throw their hands up and decide that the Egyptians must have had help from aliens …

Entry published December 3, 2007. Read full entry.

Where is Django’s blog application?

In terms of people looking for sample code or example applications to use/learn from, “where can I find a good Django-powered blogging application” is probably at the top of the frequently-asked questions list both on django-users and in the IRC; part of this is simply that, right now, there is no “definitive” Django blogging application; there are a bunch of them available if you go looking, but you’re not likely to get anyone to recommend one of them as “the” Django blogging app (unless the person doing the recommending …

Entry published November 29, 2007. Read full entry.

Keeping up with the Django

Thanks to a couple big projects at work that I’m trying to finish up in time to devote my full weekend to the sprint, I don’t have anything directly code-related to throw out today. Fortunately, there are plenty of things people ask about Django which have nothing whatsoever to do with code, and I can deal with one of them today: how do you keep up with Django development?

Every so often, people pop up on the mailing lists, or on IRC, after doing an svn up of their Django …

Entry published November 29, 2007. Read full entry.

Performance tips

Nearly two years ago, Jacob posted a round-up of useful tips for Django performance, geared mainly at the non-Django portions of your stack; suggestions like having dedicated media and database servers, memcached, plenty of RAM and database tuning really aren’t Django-specific. Two years later, all of his tips are still relevant and will still have an impact on the performance of your Django-based stack.

This leaves wide open the question of how to squeeze every last bit of performance out of Django — and your Django-based applications — though, so …

Entry published November 27, 2007. Read full entry.

Django sprint

I’ve got a couple articles brewing in the back of my head to finish out the month (and not a bad month, even with the unexpected break last weekend), but rather than write one of them tonight I’d like to pause and remind everyone that this Saturday — December 1 — is a major sprint day for Django. We’re hoping to make quite a bit of progress on some as-yet-unfinished features which need to land before Django 1.0 (the last sprint was an amazing leap forward, and it’d be …

Entry published November 26, 2007. Read full entry.

Newforms, part 3

Now that I’ve got the user-profiles application out in the wild, let’s take a look at one last important feature of Django’s newforms library: the ability to dynamically generate forms “on the fly” from model classes, via the helper functions form_for_model and form_for_instance. And, just as importantly, let’s look at why they shouldn’t always be the first thing you reach for when you need to build a form.

How model-generated forms work

We’ve already taken a look at how to introspect Django models using Django’s own internal APIs, and if …

Entry published November 25, 2007. Read full entry.

User profiles

Django, as you hopefully already know, provides a way to store additional information related to a User via the mechanism of setting up a site-specific user profile model, and supports this directly via the get_profile() method on every User object.

By way of supporting this, back in version 0.2 of django-registration I added the ability to specify a callback function which, upon creating a new User, could also create a default site-specific profile for that User; at the time it seemed like a good way to handle …

Entry published November 24, 2007. Read full entry.

Newforms, part 2

Yesterday we took a look at how Django’s newforms library works and explored the different components, how they fit together and how the overall process of form validation takes place inside a newforms form. And while that’s all useful knowledge, it’s helpful to have some practical examples to see all of the various bits in action, so today we’ll look at a simple example which shows off some of the features, building it up step-by-step.

The specific example I’ll be using here is a user-registration form; about a year ago I …

Entry published November 23, 2007. Read full entry.

Newforms, part 1

If you’ve ever had the pleasure (and I use that term somewhat loosely) of working with Django’s original form-processing system (which now lives in django.oldforms and is in the process of being deprecated), you’ll know that the replacement currently under development (which currently lives in django.newforms and will eventually become simply django.forms) represents an immense simplification and adds quite a few capabilities which weren’t present before. But because it’s still quite new (and parts of it are still being developed), it’s still not fully documented, and so can be …

Entry published November 22, 2007. Read full entry.

Auth tips and tricks

Django’s bundled authentication framework is stupendously useful as an out-of-the-box solution for common user-authentication needs, and provides a ton of things basically for free: users, permissions, groups, login/logout functionality, middleware for automatically detecting the user’s identity, the ability to restrict views based on various attributes (including staff members, superusers, permissions and arbitrary tests), the list goes on and on. For probably 90% or more of the applications you’ll develop, the simple combination of the User model and the built-in login/logout views and middleware will take care of your needs just …

Entry published November 21, 2007. Read full entry.

Initial data and install-time code

A fairly frequently-asked question is something along the lines of “how do I provide some data which gets installed along with my application?”, or some variation on that, often including questions about how to ensure a particular bit of code is run when the application is installed via syncdb. Django provides several different ways of approaching this, depending on the exact situation and exactly what you need to do, and while they’re mostly documented it still seems to cause a lot of questions. So today let’s run down the …

Entry published November 21, 2007. Read full entry.

My streak ends

First up, the bad news: my streak of one Django-related post per day in November is going to come to an end tomorrow. Some Thanksgiving plans (technically pre-Thanksgiving by a week, but nothing wrong with celebrating a little early) I’d had which were first on, then off, and are now on again, will be taking me out of town and probably offline from tomorrow morning through Sunday night. I toyed with the idea of putting together four entries and post-dating them to show up at the right times, but things …

Entry published November 14, 2007. Read full entry.

Instant web sites

As much fun as it is to write about features of Django which aren’t that well documented, or which aren’t documented (_yet_; one of my goals with each sprint we do is to add to Django’s documentation and bring it closer to being truly comprehensive), there are a ton of features in Django that, while documented, don’t seem to get a lot of use. Which is a shame, because some of them are extremely powerful and make it almost trivial to accomplish otherwise-complex tasks.

So today let’s look at two of …

Entry published November 13, 2007. Read full entry.

More on admin documentation

Since the last entry on admin documentation tricks seems to have been popular, and showed off a couple lesser-known things you can do, let’s take another look at the admin documentation system, and a couple more things you might not know about; in fact, until today I didn’t know about them, so if nothing else this entry will remind me that they exist and that I need to use them more.

Admin docs: a quick recap

In all Python programs, not just Django applications, you’re encouraged to provide documentation embedded directly in …

Entry published November 12, 2007. Read full entry.

comment_utils 0.3

Since it’s Sunday and nobody’s reading right now, I’ll sneak in a release announcement instead of a pure “Django tip”: I’ve just released version 0.3 of comment_utils.

I’ve been running it for a little while, and it seems to be fine; if you run into any problems, please file a bug report.

Fixes and tweaks

Two big changes in this version are Unicode support and accommodations for a new method of template variable resolution.

As I wrote yesterday, Django’s Unicode merge means that anything which talks to external web-based …

Entry published November 11, 2007. Read full entry.

Unicode in the real world

Django’s Unicode branch merged back over the summer, but I imagine there are a lot of people who are still using pre-Unicode versions of Django and so haven’t started updating their code yet (it was several months before I had fully updated this site, for example). For the most part, updating to work with post-Unicode Django is pretty easy (and made even easier by Malcolm’s handy checklist), but there are still some things you’ll need to be careful about; one in particular is how to handle external APIs …

Entry published November 10, 2007. Read full entry.

Living without projects

The official Django tutorial walks you through the process of developing a Django application inside a Django project; in this view of the world, the “project” is seemingly the major focus, and the “application” just happens to be something you stuff inside it. For the purposes of learning and exploring Django — especially if you’re new to Python and unfamiliar with things like how to create your own modules and set up your Python path — this is a pretty good way to work, because it means that django-admin.py and …

Entry published November 9, 2007. Read full entry.

Moving into production

At some point, every Django-based project (hopefully) moves out of the development phase and into production deployment, and this can be a traumatic experience. As a result, there are a few things you’ll nearly always want to do during this process in order to transition smoothly and ensure you go to production with all your code humming along; this time around we’ll look at a few of the more common items, and if I miss out on something you’ve found useful, feel free to mention it in a comment. …

Entry published November 8, 2007. Read full entry.

Documentation bookmarklets

Django’s admin application is capable of generating and displaying a variety of useful documentation (though once newforms-admin lands, that will be broken out into a separate documentation-only application), including lists of installed models and registered template tags, and a listing of valid URL patterns and the view functions they map to, along with the docstrings of those functions. But it also contains a page of bookmarklets — bits of JavaScript to be dragged into your browser’s bookmarks bar, and then clicked from various pages on your site — which enhance …

Entry published November 7, 2007. Read full entry.

URLConf tips and tricks

I’ve written a couple of things recently talking about useful things to be aware of when you’re putting together the URL configuration for a Django application — one covering a pitfall you should watch out for with regular expressions and one touching on the utility of the “url” tag and the “permalink” decorator, and the “reverse” utility — but you can never have too much useful information about URL configuration, because for a lot of people it seems to be one of the trickier parts of Django. So let’s look …

Entry published November 6, 2007. Read full entry.

Server startup” and its discontents

A fairly common question people ask on the Django mailing lists and in the IRC channel is “how do I have something run when the server starts up?” This is a somewhat tricky question to answer, because in many ways there’s no concept of “server start” in Django, and because the reasons behind the question vary from one use case to the next. So let’s take a look at just what people are wanting to do at “server start”, what that means (and, just as importantly, what it doesn’t mean) …

Entry published November 5, 2007. Read full entry.

Working with models, part 2

Now that we’ve got a handle on how to generically load models without necessarily knowing in advance which models, it’s time to start looking at interesting things we can do with them once we’ve got them. There are lots of uses for code which can introspect any model and extract information from it, some of which you’ve probably already seen:

Entry published November 4, 2007. Read full entry.

Working with models, part 1

In order to do all the things it does, Django has to contain quite a bit of generic code that’s capable of working with pretty much any model or combination of models you want to throw at it, and has to be able to introspect those models to get information about their fields, their relationships and other useful tidbits. There are also plenty of real-world use cases where your code needs to be able to do the same sorts of things, and so knowing how Django does it — and …

Entry published November 3, 2007. Read full entry.

Handle choices the right way

A lot of common use cases involve a model field which needs to accept values from a restricted set of choices; for example, a field for selecting a US state should, logically, only allow values which correspond to actual US states. In Django’s ORM, this is represented by using the “choices” argument when defining the field, and generally this provides a fairly easy solution.

But it’s not always perfect: while string-based values (such as those for a US state field, which are — in Django’s implementation — simply two-letter postal …

Entry published November 2, 2007. Read full entry.

Django tips: template loading and rendering

I’ve been reminded today by Maura that November is National Blog Posting Month, when — in theory — bloggers the world over try to keep up a pace of one entry every day. I don’t know how well this is going to go, but I’d like to give it a try. And, inspired by Drew McLellan’s excellent 24 ways “advent calendars” of web-design tips, I’m going to give it a theme: one Django tip every day during the month of November. Kicking off the series, I’d like to focus …

Entry published November 1, 2007. Read full entry.

Be careful with your URL patterns

Tonight in the Django IRC channel, someone stumbled across a seemingly-odd error when trying to use a generic view:

TypeError: object_list() got multiple values for keyword argument 'queryset'

The problem turned out to be the URL pattern which was routing to the generic view. Consider a simple example, as might be found in a weblog application:

from django.conf.urls.defaults import *
from weblog.models import Entry

info_dict = {
    'queryset': Entry.objects.all()

urlpatterns = ('',
    (r'^(index|weblog)/$', 'django.views.generic.list_detail.object_list', info_dict)

The idea here …

Entry published October 14, 2007. Read full entry.

Another django-registration update

This one’s just a quick heads-up, but if you’re following django-registration you’ll want to take note: I’ve been doing a series of minor releases since 0.3, and it’s now up to 0.3p5.

There have been a few bugfixes since 0.3 that you’ll want, and also some important changes:

Entry published October 7, 2007. Read full entry.

Standalone Django scripts

In the grand tradition of providing answers to frequently-asked questions from the django-users mailing list and the #django IRC channel, I’d like to tackle something that’s fast becoming the most frequently-asked question: how do you write standalone scripts which make use of Django components?

At first glance, this isn’t a terribly hard thing to do: Django’s just plain Python, and all of its components can — in theory — be imported and used just like any other Python modules. But the thing that trips most people up is the need, in …

Entry published September 22, 2007. Read full entry.

django-registration update

For those of you who are using/following it, I’ve just pushed out django-registration 0.3. The basic workflow of the application is still the same:

  1. User signs up for account.
  2. User receives activation email.
  3. User clicks link in email to activate account.

But under the hood quite a few things have been rearranged to make the application cleaner and more extensible, and there have been a couple of backwards-incompatible changes for anyone using an older version. Here’s how it breaks down.

Backwards-incompatible changes

You’ll now need to create one extra template — registration/activation_email_subject.txt — in order …

Entry published September 19, 2007. Read full entry.

Django sprint wrap (for me)

I don’t know whether anyone else is going to continue on for the rest of the night, but I’m exhausted and I’ve got to be at work in the morning.

Today, for me, consisted of reading every open ticket in Trac and doing as much triage as I could; a lot of duplicates got closed, a lot of similar issues got consolidated, a lot of ancient tickets which have either been fixed or invalidated were marked as such.

Some highlights of the last 36 hours:

Entry published September 16, 2007. Read full entry.

Sprinting all the day long


So the “official” Django sprint day is over, though (in my time zone, at least) work actually started yesterday and looks like it’ll keep on going into tomorrow. Already the amount of activity (as measured by the Trac timeline) is simply astounding, and that’s likely to continue; there have been about 150 commits so far, and I couldn’t even begin to count the number of patches that have been filed and the number of tickets which have been triaged.

I got a bit of a late start today and focused …

Entry published September 15, 2007. Read full entry.

Tips and tricks

In a few days it’ll be the weekend and I’ll (hopefully) have a bit of news regarding updates to the various applications I spun out during the process of rewriting all the code I’m using here, as well as the first official release of the blogging application I’ve developed (you can probably already find it if you know where to look, but for now it’s neither documented nor supported). In the meantime, there are a few minor and miscellaneous — but still useful — tricks I’ve started using which are …

Entry published September 6, 2007. Read full entry.

ORM Wars

Last week while I was still on blog hiatus, Adam Gomaa wrote up a pretty constructive summary of why he prefers SQLAlchemy over the default Django ORM, and documented how he made SQLAlchemy a little less painful to use by writing a set of helper functions before moving on to announcing that he’s writing his own declarative layer — borrowing somewhat from Django’s model syntax — on top of SQLAlchemy.

I went back and read a few of Adam’s other posts, and generally I like what I see; he manages …

Entry published September 4, 2007. Read full entry.

Django, Accelerated

As of yesterday, this site is served from a Joyent Accelerator, running Django via Apache/mod_python backed by a PostgreSQL database. This setup probably isn’t for everybody, but if it’s right for you (and only you can make that call), here’s how I got everything running.

First things first

Make sure you’ve taken preliminary steps to secure your Accelerator before you do anything with it; this means things like setting up key-based SSH authentication and turning off password-based login, disabling SSH logins by root, etc.; the Joyent wiki has a “getting …

Entry published September 4, 2007. Read full entry.

Honey, I’m home

If you’re seeing this, congratulations: the DNS changes have propagated and you’re seeing this site, in all its redesigned glory, at its new home: a Joyent Accelerator.

This took quite a bit longer than I’d expected, largely because — while ostensibly working on redesigning the site and re-writing the blog application which powers it — I kept feeling the urge to spin off various bits of functionality into their own generic, standalone applications. Now I’m finally putting all that work to good use, and does it ever feel good.

Oh, …

Entry published September 3, 2007. Read full entry.

A quick survey

As you’ve hopefully noticed if you’re following things in the world of Django, the Unicode branch merged today, which means that Django is now safe for Unicode at every level (pending any bugs which need to be fixed). That’s great news for users of Django.

But it also means that developers of Django-based applications need to be aware of how Django handles Unicode and watch out for boundaries between Django and any bits of software which aren’t so enlightened.

Which is where you come in.

Over the past couple of months I’ve spun …

Entry published July 5, 2007. Read full entry.

Hacking comments without hacking comments

Way back when I first set up this site, and threw together a minimal blog application to power it, I didn’t bother much with enhancing Django’s comment system. But later on, when I started getting a lot of comment spam (trivia: as of this moment, 15,153 comments have been posted here, and 14,406 of them — roughly 95% — have been spam) I realized I needed to do something, and quickly hacked Django’s comments application to add moderation.

At the time it seemed a reasonable thing to do, but …

Entry published June 25, 2007. Read full entry.

Hypothetical framework choices

I subscribe to feeds of items tagged with “django” on a couple of sites, and tonight I noticed a link which posed a hypothetical situation of wanting to port a large J2EE application to either Rails or Django, and asking about making the choice between them.

I wrote up a reply, but attempts to post it there netted me “The page you were looking for was not found. Moron.” So here it is in all its glory; maybe someone will get some use out of it, maybe not.

Choose wisely

As …

Entry published June 2, 2007. Read full entry.

django-registration update

I’ve just packaged up version 0.2 of django-registration; there are two big changes since the initial release which are worth mentioning (and which are, of course, covered in the documentation supplied with the download):

  1. The key_generated field was removed from the RegistrationProfile model, so you’ll want to drop the corresponding column in your database if you upgrade.
  2. A mechanism for automatically creating custom user profiles during signup was added; check the documentation for notes on how it works.

Also, a few bug fixes and minor enhancements went in; there’s a changelog in …

Entry published May 29, 2007. Read full entry.

Software Update

Back when I first launched this site (about a year ago now), I mentioned that I’d someday release the blog application I’d written to power it. So far I’ve been held up by two large problems:

  1. The application itself was written using an SVN checkout of Django from April of last year, back when the codebase that became the Django 0.95 release was still known as “the magic-removal branch”.
  2. Some features (notably, a couple things I’ve done with comments) relied on hacking the source of Django itself.

So I’ve been on a mission …

Entry published May 28, 2007. Read full entry.

Django template utilities

In the course of working on a couple personal projects (which will be released eventually), I found myself factoring out a lot of common code and making it more and more generic, until one day I realized I had a whole separate application just waiting to be documented and bundled.

So here it is: template_utils, a collection of generic and useful tags, filters and other tools related to Django templates. Full documentation is on the project wiki at Google Code, and distributed with the download.

Even though I’m using most …

Entry published April 12, 2007. Read full entry.

Reusable Django apps

A little while back I released a couple of Django apps to the world, and I’ve got a couple more in the pipeline (whenever some more of my copious free time rolls around, I’ll finish them up and get them out the door as well), so I’ve been thinking a bit about best practices for making them as easily reusable as possible. And James Tauber has started up a mailing list for discussing a Django application repository (anyone who’s interested in that should join up and get the discussion going), …

Entry published March 27, 2007. Read full entry.

Django snippets

Just in case you’re not subscribed to the Django mailing lists and/or aren’t at PyCon, today I launched a little side project I’ve been working on: djangosnippets.org, a site for Django users to share useful bits of code.

There are still a few things I’m working out (like feeds), but on the whole I’m pretty happy with it :)

Entry published February 25, 2007. Read full entry.

PyCon 2007: Web frameworks panel

(this was liveblogged during the panel, and the only later edits were to correct a couple of typos and add this notice — the content has not been changed)

Titus, the moderator, has welcomed everyone. No blood shed so far. Probably not taking audience questions.

Introduction of the panelists:

Titus pauses: “The most interesting thing about Django is, it’s what Guido would do.”

Titus says he’ll spark discussion by targeting Zope. First question: there’s a wide range of …

Entry published February 23, 2007. Read full entry.

PyCon 2007: the prelude

So, I’m in Dallas, eagerly awaiting the beginning of the non-tutorial bits of PyCon 2007; I got here around 4:15PM (after a lovely flight where I was inadvertently bumped to first-class), and already things are rocking; I just got back from dinner and drinks with some folks who are doing really cool stuff with and to Django. Already got some interesting ideas and things to continue fleshing out, and I’ve got another four days to spend here.

If anyone’s looking for me, I’m lounging in my room in the …

Entry published February 22, 2007. Read full entry.

About model subclassing…

In Django 0.90 and 0.91 we offered the ability to subcless models, and a nasty hack called replaces_module which would let you tell Django to use a subclass in place of the original model it was inheriting from. The magic-removal changes broke that ability, and we’ve been slowly working toward getting it back (well, actually Malcolm has been rolling the Sysiphean rock up the hill and the rest of us have mostly been urging him on). I’d say it’s probably tied with automated database migrations as the feature people most …

Entry published February 20, 2007. Read full entry.

Python framework design

Lately I’ve found myself being baited into the same old debate over and over and over again, and I’m getting tired of making the same arguments each time. Usually it begins with someone lamenting how Django is anti-community or too inflexible or generally suffering from a raging case of NIH. From there it progresses into people proclaiming how TurboGears or (more often) Pylons is objectively “better” because of how they’re designed, and how it would be nice for Django to follow their lead.

Before I go any further, I’d like …

Entry published February 19, 2007. Read full entry.

OpenID delegation under Django and lighttpd

There’s been lots and lots and lots of buzz around OpenID in the last couple weeks, which makes me happy because OpenID is a pretty darned cool system. Simon is doing all sorts of cool things, and Sam Ruby wrote up wonderful step-by-step instructions for OpenID delegation, which lets you use your own domain name to sign in with OpenID even if your OpenID is hosted somewhere else.

I sat down tonight and worked out how to set it up here, because that’s a nifty and useful trick; Sam’s Apache …

Entry published January 8, 2007. Read full entry.

My site is smarter than I am

Looking through my stats today, I found an incoming link from a blog written entirely in Chinese. Now, I don’t read Chinese (I know about half a dozen words of Mandarin, but couldn’t begin to pronounce them with the right tones), so I ran it through Babelfish and found that this person was — apparently — commenting on how “comforting” my site was to him.

This left me somewhat befuddled, until I went back and looked at the comment he’d left here, and then at his screenshot of, sure enough, …

Entry published November 22, 2006. Read full entry.

Django tips: get the most out of generic views

Recently at work I had the chance to revisit an application I’d written fairly early on in my tenure at World Online; I was still getting used to doing real Django development and to some of the quirks of our development environment, and ended up writing a lot more code than I needed to, so I was happy to be able to take a couple days and rewrite large chunks of the application to be more efficient and flexible.

The biggest win was more careful use of generic views, which this …

Entry published November 16, 2006. Read full entry.

Django tips: auto-populated fields

One of these days I’m going to run out of frequently-asked Django questions to answer. But today isn’t that day, so let’s look at one of the most common questions people ask: how do you set up a model with one or more fields that never show up in add/edit forms, and get automatically populated with some specific value?

A simple example

Let’s say you’re writing a to-do list application, and you want to have fields on the list model to store the date it was created and the time it was …

Entry published November 2, 2006. Read full entry.

Django and NIH

Just so you know, Django is a smug, arrogant framework that doesn’t play nice with others. The developers are smug, arrogant assholes who don’t care what anyone else does or what other tools are available, and who always insist on doing things their way. Django absolutely refuses to support cool “standard” Python tools and libraries unless they were implemented first for Django. Just stay the hell away from it, and teach those goddamned Django people a lesson by doing so!

Or at least, that’s the impression you’d get from reading the …

Entry published October 21, 2006. Read full entry.

How I got here

I’m not a formally-trained programmer. I wasn’t a computer science major in college (my degree is in philosophy), and my first job after graduation didn’t involve programming (it was phone-based customer service at a health-insurance company). But here I am, developing software for a living.

I’ve never written a compiler. I’ve never hand-tuned something by dropping in bits of assembly, or even by writing C extensions for an interpreted language. I’m too young to have ever hacked on a Lisp Machine. But here I am, developing software for a living.

My language …

Entry published October 16, 2006. Read full entry.

Heads up

If you’re a regular reader of my blog it will be purely remedial reading, but an article I wrote about Django is up at Sitepoint as of this morning.

Go forth and spread the good word.

Entry published October 11, 2006. Read full entry.

Django tips: laying out an application

Continuing the theme of dealing with common questions from the Django mailing lists and IRC channel, today we’ll look at how to organize the various bits of a Django-based project or application.

Projects versus applications

This is really more of a separate (though related) question, but understanding the distinction Django draws between a “project” and an “application” is a big part of good code layout. Roughly speaking, this is what the two terms mean:

Entry published September 10, 2006. Read full entry.

Django tips: documentation and resources

Django’s official documentation often draws praise for being well above average for an open-source project, but it’s far from being the only source of useful information for a developer using the framework. Also, articles and tutorials specific to Django aren’t the only useful documentation out there; the Python language in general tends to have tons of great resources. So let’s take a look at some resources you might not know about but should.

Python in general

For someone who’s new to programming in general, or for a programmer who’s new to Python, …

Entry published September 4, 2006. Read full entry.

Django tips: user registration

One of the most common and, generally, most successful models for letting people sign up for user accounts requires the user to go through some form of “activation”; usually it looks something like this:

  1. User fills out a form with a username, password and email address.
  2. User gets an email with a “confirmation link” which must be clicked to activate the account.
  3. User clicks the link and the account becomes active; then they log in normally.

So let’s look at how to do this with Django.

Also, before we dive in, let me note that …

Entry published September 2, 2006. Read full entry.

Friday fun

It’s the end of the week and, while I’ve got plenty of things I could write about, I’m sort of tired and burned out. So let’s just look at a couple things that went on this week.

Django performance with foreign keys

There’s been a bit of a to-do the last few days over a supposed performance problem in Django. I have a hard time classifying it as a “bug”, though — the whole thing centers around the fact that, to generate an HTML select box of possible choices for a …

Entry published September 1, 2006. Read full entry.

The best of all worlds

Every once in a while, someone will complain on the Django users mailing list that they feel our ORM doesn’t offer all the features they need, and it’s true that there are a few exotic and/or advanced things that it can’t handle. Usually the standard people compare to is SQLAlchemy which can be, unfortunately, extremely complex to learn and use. A related — and inaccurate — complaint is that it’s possible to use Django with SQLAlchemy, but that you’d lose the admin app (you wouldn’t; using the admin while your …

Entry published August 29, 2006. Read full entry.

Django tips: using properties on models and managers

While working on a little side project this week, I ran into a couple of very common use cases that often result in a lot of extra typing:

  1. Defining a BooleanField, or an IntegerField or CharField with choices which will, logically, break up instances of the model into certain groups which need to be accessed often.
  2. Repeatedly wanting to calculate a value based on the values of several fields of a model.

Let’s look at how to handle these common cases, while reducing the extra typing and making them behave in an …

Entry published August 18, 2006. Read full entry.

Django tips: A simple AJAX example, part 2

Last time around we looked at how to write a simple view which processes a form and either returns errors or returns success, and then tweaked it slightly so that the same view could handle either a “regular” form submission (in which case it operates normally), or an XMLHttpRequest (in which case it returns JSON).

Today we’ll look at writing the JavaScript side of it; for reference, here’s the live example we’re going to build. This will be a fairly long write-up, but that’s not an indication of the …

Entry published August 5, 2006. Read full entry.

Django tips: A simple AJAX example, part 1

One thing that’s come up over and over again in the Django IRC channel and on the mailing lists is the need for good examples of “how to do AJAX with Django”. Now, one of my goals in life at the moment is to try to fill in the gaps in Django’s documentation, so…

Over the next couple of entries we’re going to walk through a very simple form, which will submit via AJAX to a Django view and handle the result without a page refresh. If you’d like, you can …

Entry published July 31, 2006. Read full entry.

Helpers, scaffolding, tradeoffs and other stuff

In one of the very, very few coherent things I’ve seen him say in comments posted here and elsewhere, one Lucas Carlson brought up the other perceived advantage of JavaScript helpers: they save time:

Sure it is possible to add javascript helper functions to Django, and yes that would speed up initial development times and reduce bugs since Python is usually more terse than JS… even for expert JS programmers.

I’m going to ignore the “fewer bugs” argument because it seems to me that writing code in …

Entry published July 17, 2006. Read full entry.

Django tips: Hacking FreeComment

Django’s bundled comments application (found in django.contrib.comments) is incredibly useful; it gives you a nice, out-of-the-box system for adding comments to any site. But, if you look at it closely, really feels more like two applications:

  1. The Comment model and its helpers, which only allows registered user accounts to post comments.
  2. The FreeComment model and its helpers, which allows anyone at all to post comments.

The first one — based around Comment — is much more complex by far, and includes pretty much everything World Online has ever needed for its …

Entry published July 16, 2006. Read full entry.

JavaScript, ORM and “hiding SQL

So my little rant on AJAX support in Django apparently touched a nerve with a couple people; that means it’s time to write more about it.

One of the common points people have been raising, in comments and elsewhere, is that I shouldn’t rail against “hiding JavaScript from the developer” when Django’s ORM already hides SQL from the developer; from the perspective of a server-side developer, SQL is just as important, right?

Yes, SQL is just as important. But having ORM isn’t “hiding SQL”.

What ORM is

The intialism “ORM …

Entry published July 4, 2006. Read full entry.

Django tips: scaling an application

In today’s ripped-from-the-mailing-list Django tip, we’ll be looking at a common scaling pattern: an application which starts out with one user, then has to gain separate “instances” for each of multiple users. And for bonus goodness, we’ll scale it even further to work on multiple sites simultaneously.

Let’s build a blog

For purposes of this example, let’s say that you’re building a blog with Django; that was the example in the mailing-list thread, so I’ll run with it, but there are lots of types of applications that could go through this process. …

Entry published July 3, 2006. Read full entry.

Django and AJAX

One hot topic that keeps coming up over and over again on the Django mailing lists and in IRC has to do with when Django will get “AJAX support”. There are two answers to that question; one can be stated with authority, and the other consists entirely of my own unofficial and non-binding opinion. Let’s start with the first:

We’ve already got it, and more is on the way

Doing AJAX with Django has always been pretty easy, though maybe in a way that’s not obvious to users of other frameworks. …

Entry published July 2, 2006. Read full entry.

Django tips: the difference between ‘blank’ and ‘null’

New users of Django, even people who have lots of experience writing database-driven applications, often run into a seemingly simple problem: how do you set up a model with “optional” fields that don’t always have to be filled in? Django’s validation system assumes by default that all fields are required, so obviously you have to tell it which fields it’s OK to leave blank.

But therein lies the problem: there are two different ways you can “leave it blank”.

There’s nothing…

For the most part, assuming that fields should be required is a …

Entry published June 28, 2006. Read full entry.

Django tips: Template context processors

Last time around we looked at how to write an effective template tag, with the focus on writing a flexible template tag that would make it easy to pull in various types of recent content in any page; I use a tag similar to the one in that entry to pull out the recent entries, links and comments in the footer of every page on this site.

For situations where you want to get content out of your database, a template tag is typically the best way to go, but …

Entry published June 14, 2006. Read full entry.

How Django processes a request

In a comment he left yesterday, Jonathan Snook posed an excellent challenge: document the chain of how Django processes a request, from start to finish, with plenty of detail on the various things being called internally and links to the appropriate documentation.

Simon Willison once wrote such a document, but it was a fairly high-level view and a fair number of things have changed since then, so I’m going to take a stab at it myself, and hopefully the result will be comprehensible.

Note: this is a first draft. Not …

Entry published June 13, 2006. Read full entry.

Django tips: Write better template tags

Django‘s template tags are a great way to handle things that don’t always make sense being in a view. If you want to have, say, a list of recently-added content which appears in a sidebar or footer on every page of a site, it’d be crazy to manually change every view to fetch that content and add it to the template context; a template tag is definitely the way to go.

For example, in the footer of every page on this site, I pull out the five most recent entries, …

Entry published June 7, 2006. Read full entry.

Django tips: extending the User model

One of Django‘s great strengths is its built-in user and authentication system; the bundled application django.contrib.auth includes models for users, user groups and permissions and views for logging users in and out and changing and resetting their passwords. This is enough to cover the needs of a huge number of sites and, after the admin, the auth system is probably the most popular bundled application Django ships (or maybe the other way around, since the admin requires the auth system to be installed).

Because of the auth system’s popularity, though, …

Entry published June 6, 2006. Read full entry.

Templating languages redux

So, I thought I’d explained why templating languages are pretty useful things. Markup is, after all, just about the fastest and simplest way to, well, mark up content for presentation and, when coupled with a small amount of logic, is by far the best way to present the output of a dynamic database-driven web application. I kind of hoped that I wouldn’t have to write more on the topic, because there are so many more interesting things to which I can devote my time.

Sadly, I was mistaken. Enter one …

Entry published June 5, 2006. Read full entry.

Why templating languages aren’t a bad idea

Before I get into any meaty details, a quick question. You have a dynamic, database-driven web application and you’re ready to sit down and bang out its HTML output. One part of one page will be an ordered list containing comments left by visitors. You have the following choices for doing this:

Option A:

<ol class="comments">
{% get_comment_list %}
{% for comment in comment_list %}
<li>{{ comment }}</li>
{% endfor %}

Option B:

item = page.new_content_element('ol')
item.class = 'comments'
for comment …

Entry published May 24, 2006. Read full entry.

Django, gzip and WSGI

One of the many things I like about Django is the range of available middleware you can use to do all sorts of interesting stuff. But one in particular has got me a little bit stumped.

One of the available middleware components for Django allows content to be gzipped for output when the client specifies ‘gzip’ in its Accept-Encoding header; this is handy because it both conserves bandwidth and allows pages to be downloaded more quickly. Most popular web servers allow this (Apache via mod_deflate, lighttpd via mod_compress, etc.), …

Entry published May 21, 2006. Read full entry.