Everything that I have built in Django so far has been pretty simple. Perhaps “limited scope” is a better choice of words. Each project I create tends to only contain one user-created app. There are a couple of sites that I’d like to build which could share some code between them. So, I decided to look into using multiple user-created apps and seeing how things fit together. My primary interests in this exercise were the url configuration and template inheritence among applications.

I created a project named “mproject” and, for the sake of simplicity, three apps named “main_app”, “foo_app”, and “bar_app” under the “mproject” directory. In addition to the autogenerated files, I created a “urls.py” for “foo_app” and “bar_app” and one html template for each of the three apps (named “bar_main.html”, “foo_main.html”, and “base.html”). Here is a tree view of the directory structure:


.
`-- mproject
|-- __init__.py
|-- bar_app
| |-- __init__.py
| |-- models.py
| |-- templates
| | `-- bar_main.html
| |-- urls.py
| `-- views.py
|-- foo_app
| |-- __init__.py
| |-- models.py
| |-- templates
| | `-- foo_main.html
| |-- urls.py
| `-- views.py
|-- main_app
| |-- __init__.py
| |-- models.py
| |-- templates
| | `-- base.html
| `-- views.py
|-- manage.py
|-- settings.py
`-- urls.py

I added the following three lines to the INSTALLED_APPS section of my settings.py file:

'mproject.main_app',
'mproject.foo_app',
'mproject.bar_app',

This is how applications are “plugged in” to your Django project.

I added the following to the project-level urls.py:

(r'^foo/', include('mproject.foo_app.urls')),
(r'^bar/', include('mproject.bar_app.urls')),

This says to use everything in the foo_app.urls url configuration, but map it by prepending “foo/” to all those entries. Likewise for bar_app.urls and “bar/”.

main_app/views.py is empty. Since this is a simple example, the main application isn’t doing anything.

main_app/templates/base.html:

<html>
<head>
<title>{% block title %}Main Base Title{% endblock %}</title>
</head>
<body>
{% block content %}
Unset Content
{% endblock %}
</body>
</html>

bar_app/urls.py:

urlpatterns = patterns('',
# Example:
# (r'^mproject/', include('mproject.apps.foo.urls.foo')),

# Uncomment this for admin:
# (r'^admin/', include('django.contrib.admin.urls')),
(r'^main/', 'mproject.bar_app.views.main'),
)

I only created one mapping for this app. “main/” will map to the function mproject.bar_app.views.main. But, since the main url config is including this url config, “/bar/main/” will map to the mproject.bar_app.views.main function.

bar_app/views.py:

from django.shortcuts import render_to_response

def main(request):
return render_to_response('bar_main.html', {})

This simply links the “main” function with the “bar_main.html” template.

bar_app/templates/bar_main.html:

{% extends "base.html" %}

{% block title %}Bar Title{% endblock %}

{% block content %}Bar Content{% endblock %}

Here, I’m extending base.html, which Django will pick up from the main_app application. I’m overriding the title and content blocks so that this template gets to fill in its own content.

Here are the details on foo_app, but without explanation since I’m doing the same thing here as in bar_app.

foo_app/urls.py:

urlpatterns = patterns('',
# Example:
# (r'^mproject/', include('mproject.apps.foo.urls.foo')),

# Uncomment this for admin:
# (r'^admin/', include('django.contrib.admin.urls')),
(r'^main/', 'mproject.foo_app.views.main'),
)

foo_app/views.py:

from django.shortcuts import render_to_response

def main(request):
return render_to_response('foo_main.html', {})

foo_app/templates/foo_main.html:

{% extends "base.html" %}

{% block title %}Foo Title{% endblock %}

{% block content %}Foo Content{% endblock %}

A couple of really practical uses for this come to mind. First, this is an easy way of separating logical pieces of your application. This approach makes it really easy to separate your site into its logical pieces. For example, you could have a blog, main static content, user reviews, photo gallery, etc. each in their own applications. This should lead to a less cluttered views.py file (even though you should be able to do something similar by separating things out and creating a “views” directory and putting logically separated code there).

Second, this makes for really nice sharing of applications among projects. Why not create your own customized user registration app and use it in each of your projects? Or a blog? Or photo gallery? (Or what have you.) All you have to do to re-use code is add an entry to the INSTALLED_APPS section of your settings.py file and create an include in your urls.py file.

I remember hearing or reading someone say that the pluggability of Django apps is one of its under-touted features. I couldn’t agree more. Something that I had previously avoided because I didn’t need it is turning out to be an incredibly powerful feature.

I’ve uploaded the project and app files here for anyone interested.