Django Projects

At its core, a Django project requires nothing more than a settings file. In practice, almost every project consists of the following items:

Settings

The settings module is the only true requirement for a Django project. Typically, it lives in the root of your project as settings.py.

Handling Settings for Multiple Environments

Django’s startproject command gives you a single settings.py file. If you’re new to Django, stick with the single file while you learn the ropes. As you start to deploy production sites and work with more than one developer, you’ll realize the benefit in maintaining multiple settings files. For example, you probably want to run with DEBUG on locally, but not in production.

There are numerous ways to handle multiple settings. Whatever solution you choose, it should meet the following requirements:

  • All the important settings files are version controlled. If the settings change on your production site, you’ll want to know who made the changes and when they were made.
  • All settings inherit from a common base. If you want to add django-debug-toolbar to your INSTALLED_APPS, you should be able to do it without redefining all your INSTALLED_APPS.

If you don’t want to think about it, simply use our Django project template when starting new projects. It is ready to support multiple projects out of the gate:

django-admin.py startproject --template=https://github.com/lincolnloop/django-layout/tarball/master -e py,rst,example,gitignore my_project_name

See also

Django’s Split Settings Wiki
Examples of handling multiple settings

Handling File Paths

One function of your settings is to tell Django where to find things such as your static media and templates. Most likely they’ll already live inside your project. If so, let Python generate the absolute path names for you. This makes your project portable across different environments.

import os
DIRNAME = os.path.dirname(__file__)
# ...
STATIC_ROOT = os.path.join(DIRNAME, 'static')

URLconf

By default, you’ll find your URLconf in the root of your project as urls.py. It defines how requests should be routed for your project.

Keep it Simple

Your project URLconf should simply include URLconfs from your applications whenever possible. This keeps your application logic inside your application and your project simply serves as a pointer to it.

See also

Django URL dispatcher documentation
Including other URLconfs

Handling URLconfs for Multiple Environments

Just like your settings module, eventually, you’ll come across the need to run different URLconfs for different environments. You may want to use admin locally, but not once deployed. Django already provides an easy way for you to do this with the ROOT_URLCONF setting.

This is basically the same scenario as having multiple settings. You can use the same solution here:

myproject
  ...
  settings/
        __init__.py
        base.py         <-- shared by all environments
        def.py
        production.py
  urls/
    __init__.py
        base.py                 <-- shared by all environments
    dev.py
    production.py
  ...

WSGI File

The WSGI file tells your WSGI server what it needs to do to serve your project on the web. Django’s default wsgi.py is sufficient for most applications.

Local Applications

Local applications are Django applications that are domain-specific to your project. They typically live inside the project module and are so closely tied to your project, they would have little use outside of it.

Local vs. Third Party

There are hundreds [1] of open source Django applications available. Before you reinvent the wheel, make sure somebody hasn’t already solved your problem by searching on Google or Django Packages. If you find something that will work do not put it your project code, instead add it to your pip requirements.

[1]http://djangopackages.com/categories/apps/

The Namespace

How local applications should be imported into your project is a source of ongoing debate in the Django community [2]. Fortunately, with the release of Django 1.4, the default manage.py no longer changes the PYTHONPATH [3], making this much less of an issue.

At Lincoln Loop, we put project applications inside the project namespace. This prevents polluting the global namespace and running into potential naming conflicts.

[2]Discussion on django-developers mailing list regarding project namespaces in the tutorial
[3]Django 1.4 manage.py changes

Templates

Location

Templates typically live in one of two places, inside the application or at the root level of a project. We recommend keeping all your templates in the project template directory unless you plan on including your application in multiple projects (or developing it as a open source “reusable” application). In that case, it can be helpful to ship with a set of sample templates in the application, allowing it to work out-of-the-box or serving as an example for other developers.

Naming

Django’s generic views provide an excellent pattern for naming templates. Following design patterns already found in Django can be helpful for a couple reasons.

  1. They have been well thought out and tested.
  2. It makes your code immediately understandable to new developers picking up your Django code.

Most generic view templates are named in the format:

[application]/[model]_[function].html

For example, creating a template to list all of the contacts (Contact model) in my address book (address_book application), I would use the following template:

address_book/contact_list.html

Similarly, a detail view of a contact would use:

address_book/contact_detail.html

Not every template you create will map so closely to a single model, however. In those cases, you’re on your own for naming, but should still keep your templates in a directory with the same name as your application.

When using inclusion tags or other other functionality to render partial templates, keep them in an includes directory inside the application template directory. For example, if I had an inclusion tag to render a contact form inside my address book application, I would create a template for it at:

address_book/includes/contact_form.html

There is no rule (anymore) that templates must have an html file extension. If you are rendering something else (plain text, JSON, XML, etc), your templates file extension should match that of the content you are generating.

Static Media

Static media encompasses all the non-dynamic content needed for your website: CSS, images, JavaScript, Flash, etc. It comes in two flavors, user-generated content and the media needed to render your site. Best practice dictates that your static media lives inside your project and your version control system. Certainly, we don’t want stuff our users’ uploads to go to the same place. As such, we always use django.contrib.staticfiles [4].

In addition to some other slick features, staticfiles gives you a static template tag [5] that will properly locate your static files whether they are on your local computer or in a non-local storage on your production system. This leaves MEDIA_URL and MEDIA_ROOT to manage user generated content.

[4]https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/
[5]https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:templatetag-staticfiles-static