In the 48 hours since I launched the new version of this site, I’ve been inundated with questions about Django, the Python-based web application framework I used to build it. I’ve pointed many people at the official Django website, which is loaded with great information. However, most of it is aimed at programmers — and rightfully so. Django is, after all, a platform for programming web applications.
I wanted to take a moment or two while I still have your attention to tell you why I think Django is a great tool for those of us who really aren’t programmers, as well.
What is Django?
According to the official site, “Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design.”
What that means to me, as a non-programmer, is that Django is a set of core components that takes care of a lot of the programming work that goes into building web applications and other database-driven websites so I don’t have to. Those things that must be done for nearly every web site are built-in, so I can ignore them and focus on what makes each site unique. Here’s an (incomplete) list of things Django provides out-of-the-box:
- Authentication and authorization (users, groups, and permissions)
- Database connectivity (several supported databases, no SQL needed)
- Administrative interface (for adding/deleting/modifying items in the database)
- URL configuration (for making simple, clean, sexy URLs)
- Internationalization (makes localization easy)
- Feed syndication (RSS/Atom)
- Comments on any type of object (both anonymous comments, which Django calls “free comments” and comments that require registration)
- “Flat pages” (simple HTML content stored in the database and passed into a template)
Now, if you’re used to building sites using a blogging app (Wordpress, TXP, etc.) as a CMS, you’re used to getting all that for free. But you’re also getting a lot of things built-in that maybe you don’t want (unless, of course, you’re building a blog). The limitation I ran across in using a blogging app for my personal site is that I wanted it to be more than just a blog. As soon as I tried to hack a blog into a photo gallery, or a links feed, or a statistics database, a game of Sudoku, or whatever else I could think of, things started to get crufty. I also built a website in which I tried to use a discussion forums app (vBulletin) as a CMS, and that had the same results. It worked — sort of — but it wasn’t extensible, was very hackish, and just generally was inelegant.
With Django, you get all of these things and none of the limitations of a blogging app.
How do you build a program with Django?
Django loosely subscribes to the Model-View-Controller approach to programming. If you’re like me, that means almost nothing to you. According to Wikipedia, “Model-view-controller (MVC) is a software architecture that separates an application’s data model, user interface, and control logic into three distinct components so that modifications to one component can be made with minimal impact to the others.” Sound familiar? It’s quite a similar approach to the one we take in the web standards world with the structure (XHTML), presentation (CSS), and behavior (DOM scripting) layers.
In Django, we call the view layer “templates” and the controller layer “views.” Confusing? Perhaps. Here’s what the official Django website has to say on the matter:
That’s because Django isn’t strictly a MVC framework. If you squint the right way, you can call Django’s database layer the “Model”, the view functions the “View”, and the URL dispatcher the “Controller” — but not really. In fact, you might say that Django is a “MTV” framework — that is, Model, Template, and View make much more sense to us. So, although we’ve been strongly influenced by MVC — especially in the separation-of-data-from-logic department — we’ve also strayed from the path where it makes sense.
In plain English, models are the sets of fields you’ll use in your database. A basic model for a blog post would contain fields like “Title,” “Body,” “Date published,” “Tags,” etc. A simple model for an address book entry might include “Name,” “Address,” Phone number,” and so on.
Django handles the creation of your databases for you once you tell it what your model is. No need to write SQL (w00t!). Here’s what a Django model for a simple blog post looks like:
So, going through this line by line, we are:
- Creating a short text field called “title” with a maximum length of 200 characters.
- Creating a “slug” field that is automatically created from the calue of the “title” field. “Slug” is a newspaper term, but what it means here is the final bit of the URL. For example, a post with the title, “A bit about Django” would become, “bit-about-django” automatically (you can, of course, change it easily if you don’t like the auto-generated slug).
- Creating a date/time field called “pub_date” and giving it a display name of “Date published.” Django would have automatically created the display name “Pub date” if I hadn’t specified this (which probably would have been just fine for most uses).
- Creating a large text area field called “body.”
- Creating a many to many relationship (called “tags”) with another model called “Tag.” Many to many indicates that each post may have many tags, and each tag may be associated with many posts.
- Creating an image upload field called “lead_image” that will put uploaded files in img/blog-posts/lead and has the help text “Should be 706px wide” in the administrative interface.
- Creating an “author” relationship to Django’s built-in “User” model.
- Creating a simple true/false field called “enable_comments” that defaults to “True.”
From these nine lines of code, Django will create the SQL needed and initialize a database table in your chosen database (PostgreSQL, MySQL, etc.).
If you like, Django can give you a sexy, simple administrative interface where you can create, remove, delete, and update entries to your “Post” model. All you need is a few more lines of code:
These four lines create a very pretty admin area (designed by Wilson Miner) with appropriate entry fields for all of your fields. The “pub_date” field will automatically get a pop-up calendar for choosing a date. The “enable_comments” field automatically knows to use radio buttons for its interface. The “lead_image” field will be a browser-based upload tool. Et-cetera. Without doing a thing, you’ll get an admin interface the likes of this:
I’ve specified in my Admin class that I want to see the fields “title,” “pub_date,” and “enable_comments” in the list display of my posts. I’ve also said that I want a search field that searches the “title,” “slug,” and “body” fields, and that I’d like to be able to filter my posts by the date published and whether or not they have comments enabled. The list view will look something like this:
In other words, you’ve recreated Wordpress in 13 lines of code. Okay, maybe that’s a slight exaggeration — but these 13 lines are truly the most difficult thing a non-programmer will have to do to get a basic blog app running in Django.
It’s worth noting that Django admin interface is entirely optional. You could just as easily build you own admin interface. I think the built-in one is great, so I didn’t take the time to build my own.
Views are the place most serious programmers are going to spend their time in Django. The purpose of a view is to define a “type” of page within your site, and the data they need in order to serve their purpose. For example, one view in a blog app might be “post detail,” which would have access to everything you need for a page like the one you’re looking at now: a particular “Post” object and all of its related fields (as defined in our models), its associated tags and comments, etc. Views can be very simple or painfully complex, depending on what you are trying to do.
For us non-programmers, Django provides built-in views (called “generic views”) that cover about 90% of everything you’ll ever want to do. Almost all of jeffcroft.com is done with generic views. Without writing a single line of code, you get:
- Date-based views, for drilling down into date-based data. Date-based views can be used to create yearly, monthly, and daily archives of a particular model in your database — like blog posts, for example. The archive here at jeffcroft.com is an example of date-based generic views.
- List/Detail views, for displaying a list of objects and a detail page for each one. The photos section at jeffcroft.com is an example of this type of generic view (list/detail).
- Create/remove/update views, which includes a set of functions for creating, editing and deleting objects. I didn’t use this type of view here at jeffcroft.com, but it would allow me, say, to put a tag entry field on this page and let readers add tags to blog posts.
I only found one thing I couldn’t do with generic views in building this site: search. I had to write my own view for this, but found it to be astonishingly easy to do. If you can dabble in PHP, you can write a simple view, no doubt. That having been said, a built-in search engine is something I think Django would be wise to add.
Templates, for the most part, are HTML pages that have access to information in the database (by way of the view, which passes it along). I’ve already written pretty extensive entries on how Django templates work, so I won’t be redundant here. For you, the designer, templates will be the simplest and most fun part of building Django apps.
The last thing you’ll need to do in building a Django application is tie your views and templates to URLs. Django uses regular expressions for this, which allows you to do some incredibly complex things if you want to. Here’s what the URL configuration looks like for the photos section of this site:
Lets look at this bit-by-bit:
- We import the model that we’re dealing with — in this case, “Flickr_photos” in the application called “tumblelog.”
- We state that URLs that match the regular expression “^photos/$” should use the object_list generic view. It should list out items from the “Flickr_photos” model, put 56 items on each page, and use the template located at photos/photos_list.html.
- We state that that URLs that match the regular expression
(?P<slug>[^/]+)/$should use the object_detail generic view. It should, again, use the “Flickr_photos” model. The “slug field” (or, the part of the URL that comes after /photos/) is the “photo_id” in our model, and it should use photos/photos_detail.html as its template.
In plain english, this means that the URL /photos will display a paginated list of all photos using my photos_list template, and a URL like /photos/114738674/ will display a detail page for the photo with the ID “114738674” using the photo_detail template.
While this post is a bit long and may seem a bit daunting at first, the bottom line is that I’ve literally given you everything you need to write a simple application in Django. Once you have Django installed and running, you can truly build a basic CMS in thirty minutes (plus however much time you want to spend on the HTML and CSS).
Do I think you should build a CMS in Django? That depends. If all you want to do is host a basic blog, maybe not. There are already several blogging apps that have proven to be stable, robust, and feature-packed out there. Many of them are free and can be installed in 15 minutes. But if you’re finding that using a blogging app as your CMS is limiting you, or you want to create another sort of web application entirely, give Django a look.
Even you, the non-programmer, can build something very cool in not-very-much time. I built the current incarnation of jeffcroft.com in about a month at around two hours per day. A large part of that time was dedicated to learning the Flickr and del.icio.us APIs and how to parse their XML results so that I could store the data in my Django database. If I had been creating all my content on site and not pulling it in from other places, I probably could have cut the time taken to build this site in half.
If you’re looking to do more on the web, give Django a try — and let me know how it goes.