Multiple Files for Django Models

One of the first things I noticed when I started with Django was that models and views were single files. Now I’ve read various opinions on how things should be handled (multiple modules vs. multiple files) but I’m of the opinion that clarity is always better. So even if you have a single model, I’d rather have the file be named something descriptive rather than the generic

Breaking things up into multiple files is quite straight-forward – delete, create a models directory, add and create your model classes. Here’s an example:

from blog import Blog
from blogcomment import BlogComment

view raw
hosted with ❤ by GitHub

Note: In order for syncdb to see your models and work correctly, you’ll need to import the models in


from django.db import models
class Blog(models.Model):
title = models.CharField(max_length=255)
slug = models.CharField(max_length=255)
author = models.CharField(max_length=100)
blog = models.TextField()
image = models.CharField(max_length=20)
tags = models.TextField()
created = models.DateTimeField('date created', auto_now_add=True)
updated = models.DateTimeField('last updated', auto_now_add=True, auto_now=True)
def __unicode__(self):
return self.title
class Meta:
app_label = 'app'

view raw
hosted with ❤ by GitHub

Note: The Meta class is necessary for Django to associate the model correctly. Just set it to the name of your application. Otherwise syncdb won’t see your models or you’ll get a lovely error like the following when one of your models contains a foreign key:

CommandError: One or more models did not validate:
app.blogcomment: 'blog' has a relation with model <class ''>, which has either not been installed or is abstract.

view raw
hosted with ❤ by GitHub

You can then import your models like this:

# import one model
from app.models import Blog
# import a bunch
from app.models import *

view raw
hosted with ❤ by GitHub

Django Settings – Disqus Style

David Cramer posted this excellent article back in 2011 about how they handle their config files. In a multi-environment setup (dev, stage, prod) this is paramount.

In his example he makes use of an environment variable to set which configuration to use. While this is probably ideal, it’s not always an option. As a replacement, you could use the IP address or host name of the machine:

HOST_IP_ADDRESS = socket.gethostbyname(socket.gethostname())
HOST_NAME = socket.gethostname()
if string.find(HOST_NAME, '.local') is not 1:
elif HOST_IP_ADDRESS is '':
DJANGO_CONF = 'staging'
DJANGO_CONF = 'prod'
# import from the selected environment (i.e.
module = __import__('environments.' + DJANGO_CONF, globals(), locals(), ['*'])
for k in dir(module):
locals()[k] = getattr(module, k)

view raw
hosted with ❤ by GitHub

Django Class-based Sign Out Redirect

A typical use case is to provide the user a sign out button which redirects to another page such as the homepage. The following implements this using the generic RedirectView.


from app.views.signout import SignOut
url(r'^signout/$', SignOut.as_view(), name='signout'),

view raw
hosted with ❤ by GitHub


from django.views.generic.base import RedirectView
from django.contrib.auth import logout
from django.core.urlresolvers import reverse
class SignOut(RedirectView):
permanent = False
query_string = True
def get_redirect_url(self):
return reverse('home')

view raw
hosted with ❤ by GitHub

Django Class-based Views

Class-based views were introduced in Django 1.3 and are very useful. This article discusses how to make use of them along with creating a mixin for requiring the user to be authenticated for a specific view.

I’ve tweaked the example a little bit, redirecting to the login page rather than a 404 and separating the mixin into a separate file.


from app.views.about import About
url(r'^about/$', About.as_view(), name='about'),

view raw
hosted with ❤ by GitHub


from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
class RequireSignIn(object):
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated():
url = '{0}?next={1}'.format(reverse('signin'), request.path)
return HttpResponseRedirect(url)
return super(RequireSignIn, self).dispatch(request, *args, **kwargs)

view raw
hosted with ❤ by GitHub


from django.views import generic
from app.views.mixins import RequireSignIn
class About(RequireSignIn, generic.TemplateView):
template_name = 'about/index.html'
def get_context_data(self, **kwargs):
ctx = super(About, self).get_context_data(**kwargs)
return ctx

view raw
hosted with ❤ by GitHub

Django Nomenclature

The first basic thing to know is Django doesn’t use the MVC nomenclature like Symfony2 and others do. It uses MTV – model, template, view. For the most part same thing, different name.

Other naming conventions are pretty much the same – you’ve still got config files, database fixtures, routing, static files (js, css, images, etc.), logs, tests, etc.

It’s how these are implemented where the differences become apparent.

IDEs for Python and Django

As mentioned in the previous post, I’m a big fan of the IDE offerings from JetBrains (and who doesn’t love Prague). Tons of functionality, lightweight (when compared to my old friend Eclipse), lots of plugins and inexpensive.

One trick for any MacPorts users out there (yes, MacPorts, don’t judge), if you launch the application normally, you’ll end up using the system Python:

$ which python

No bueno. To fix this little inconvenience, PyCharm and PhpStorm offer the ability to create a command-line launcher:

You can then launch the IDE via the command-line and you’ll now be using the MacPorts binaries:

$ which python

Time for a Switch? PHP / Symfony2 vs Python / Django

UPDATE: Check this post for a comparison of Symfony2 and Django models.

UPDATE 2: For a framework speed comparison, check out this post.

For the past few years I’ve been using the CodeIgniter PHP framework for projects at TBWA. It’s a simple, straightforward framework that has done a solid job. New devs can get up to speed quickly on it with very little training and the framework itself is speedy enough for my purposes. But things have progressed significantly over the past couple years. I’m about to embark on a new project and it’s possibly time for something new.

After a bit of research I narrowed things down to sticking with PHP and moving to the Symfony2 framework or moving over to Python / Django. I won’t get into a debate of what language is better, faster, more elegant, more awesome, etc. There’s plenty of that out there already.

For me the choice is simple, use a language I know or make the switch to something new. Final destination for this will be a 3-tier set up on AWS or a similar cloud provider. I’m using RightScale which provides ServerTemplates for both PHP and Django, making tuning and rapid deployment (via Chef) about the same for both. So the implications of running servers for one vs the other aren’t necessarily a concern (yes, performance is a valid issue but I believe either framework can be tuned to achieve acceptable throughput as demonstrated by the sites currently using them).

Before diving into Python I decided to quickly learn Symfony2 first since I already know PHP. The framework site has a ton of clearly written docs so it was easy to get up to speed. This tutorial was also very helpful. There’s a lot going on with Symfony2 – Composer for dependency management, Doctrine for ORM, Twig for templating, Assetic for asset management, PHPUnit for testing, etc. Of course all of these can be used without Symfony2, but the framework does a nice job of making them all play nicely together. It’s clearly where PHP development is headed. It you choose this direction, I highly recommend PhpStorm as your IDE as it’s got built-in support for the framework.

With that out of the way it was time to learn some Python / Django. Having zero experience with either the language or the framework, I decided to dive right into the Django docs, picking up Python along the way. Again, many of the same features can be found with this setup – pip for dependency management, Django’s built-in ORM and templating engine, webassets for asset management, unittest2 for testing, etc. Django also has a simple admin interface that can be automatically generated which I’m sure would come in handy for some projects. The getting started docs are a little sparse in comparison but a quick Google search will usually answer any question. And again, Jetbrains has a great IDE for Django development – PyCharm.

One last factor to take into account was who is behind these frameworks. On the Symfony2 side we’ve got SensioLabs (a French digital agency) and Fabien Potencier along with multiple contributors. Django, on the other hand, is backed by the non-profit Django Software Foundation with a governance board, core team and multiple contributors. License wise, Symfony2 is MIT while Django is BSD.

Based on the title you’ve probably guessed I’ve selected Django. But first, I’ll use the next couple posts to explore some of the differences in the frameworks as well as development workflow and configuration.