Moving into production

Published: November 8, 2007. Filed under: Django.

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.

General settings changes

First and foremost, you want to flip your DEBUG setting to False; I’d hope this is obvious, but I’ve seen enough people move to production with DEBUG still on that it’s worth mentioning explicitly. Turning DEBUG off brings several immediate benefits:

  1. Django will stop displaying full tracebacks with code and settings whenever it encounters an internal error, which keeps the general public from getting a sneak peek into your application.
  2. Django will stop keeping a log of the database queries you’ve executed; when you’re debugging, this is useful, but in production it’s a resource drain you don’t want.
  3. Anything you had in your templates which keyed off the debug variable (set by the debugging context processor if you’re using a RequestContext in your view) will stop displaying, which provides a handy way to ensure that extra debugging info in your templates only displays when you’re actually debugging.

There are a couple other settings you’ll want to look at or double-check when going live:

Dealing with caching

Django’s caching framework, when enabled via the CacheMiddleware or accessed via per-view decorators or its low-level API, will cache content regardless of the value of the DEBUG setting (because, after all, you’ll often need to test performance with and without caching before going live), which raises a tricky question of how to avoid caching in development but have it enabled in production (because just as often you’ll want to bypass the cache and have changes show up immediately while you’re developing a site).

There are several methods you could use to handle this, but probably the most effective is simply to toggle the value of the CACHE_BACKEND setting; the ideal is to switch between the “dummy” backend in development and your actual caching mechanism in production. The “dummy” backend doesn’t actually cache anything, but will satisfy the need to have CACHE_BACKEND set when using the cache API or middleware, and you can even put a conditional check into your settings file to have the change happen automatically:

if DEBUG:
    CACHE_BACKEND = "dummy:///"
else:
    CACHE_BACKEND = "memcached://127.0.0.1:11211/"

Making sure errors work properly

Aside from setting up the ADMINS and MANAGERS settings to ensure that various types of errors are emailed to your site staff, you’ll also want to make sure you have two templates available in the top level of one of your template directories:

  1. 500.html will be used for internal errors which generate an HTTP 500 error; it has no context, not even the variables which would be populated by a RequestContext, because it doesn’t use that; in the event of an internal error, it’s not possible to rely on anything, including RequestContext (which needs to do database queries and introspect the HttpRequest, two things which could easily fail if something’s already errored out).
  2. 404.html will be used for any URL which doesn’t resolve, or whenever something raises an uncaught Http404 exception. It uses a RequestContext and so will apply context processors, and will also have the variable request_path available, containing the URL which generated the 404.

If these templates are missing, the actual error will be masked by a TemplateDoesNotExist raised when they’re not found, a situation which occasionally trips up newcomers to Django. The specific template names come from the views Django uses in these cases: django.views.defaults.server_error for a 500, django.views.defaults.page_not_found for a 404. You can override these in your root URLConf by assigning the dotted Python paths (as strings) of your own error-handling views to the variables handler500 and handler404, respectively.

Getting your sites straight

If you’re using Django’s sites framework (which gets listed in INSTALLED_APPS by default), an initial Site object titled “example.com” was created for you during syncdb. You generally do not want to delete this object, because code which uses the sites framework (including the admin application) relies on the existence of a Site object with an id the same as the value of the SITE_ID setting. Instead, it’s best to edit the initial Site object to reflect the domain or IP address on which you’re doing development, and then change it to your live domain when you go into production.

You should also make sure that you haven’t inadvertently copied over the SITE_ID setting from another settings file, or filled in an incorrect default value. And if you’re administering multiple sites from one project that’s running an instance of the admin, you’ll want to ensure that you’ve filled in the ADMIN_FOR setting in that project, so it’ll know that its instance of the admin is responsible for the other projects as well.

And a lot more

Everybody’s experience of going live is different, and these are just some of the most common things people seem to encounter; if you’ve run into specific problems or useful tricks, feel free to share them in the comments below.