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.
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:
- 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.
- 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.
-
Anything you had in your templates which keyed off the
debug
variable (set by the debugging context processor if you’re using aRequestContext
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:
- Fill in values for the ADMINS and MANAGERS settings if you haven’t already; Django will use these settings to email useful information (including tracebacks and notifications of broken links) to your site’s staff.
- Make sure the email-related settings are correct, particularly DEFAULT_FROM_EMAIL and SERVER_EMAIL, because many email providers will reject email which claims to come from “webmaster@localhost” or “root@localhost” (the default values of these settings) or which doesn’t come from accounts which verifiably exist. Additionally, if you don’t have a correctly-configured mail server and the proper settings to tell Django to use it, you’ll never get emails about errors on your site, or any other email generated by Django.
- If you’ve changed the value of TEMPLATE_STRING_IF_INVALID, you should set it back to an empty string; some templates (particularly in the admin) don’t react well to having a debugging string displayed when they expect silent variable failure.
- Fill in INTERNAL_IPS so Django will know which IP address(es) correspond to your company or otherwise “internal” computers which can safely see some types of information (like the information retrieved by the admin documentation bookmarklets).
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:
-
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 aRequestContext
, because it doesn’t use that; in the event of an internal error, it’s not possible to rely on anything, includingRequestContext
(which needs to do database queries and introspect theHttpRequest
, two things which could easily fail if something’s already errored out). -
404.html
will be used for any URL which doesn’t resolve, or whenever something raises an uncaughtHttp404
exception. It uses aRequestContext
and so will apply context processors, and will also have the variablerequest_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.