This article is part 3 of 14 in the series Python Django Tutorial

Last Updated: Thursday 12th December 2013

The previous article Writing Your First Python Django Application is a step-by-step guide on how to write a simple Django application from scratch. In this article, you will learn how to write models for your new Django application.

Software Architectural Patterns

Before we dive into the code, let's review two of the most popular server-side software architectural design patterns: Model-View-Controller and Presentation-Abstraction-Control.

Model-View-Controller

The Model-View-Controller (MVC) design pattern is a software architecture pattern which separates the presentation of data from the logic of handling user interactions. A model specifies what kind of data gets stored. A view requests data from a model and generates outputs from it. A controller provides logic to change the view's presentation or update the model's data.

Presentation-Abstraction-Control

Like MVC, Presentation-Abstraction-Control (PAC) is another popular software architectural pattern. PAC separates the system into layers of components. Within each layer, the presentation component generates output from the input data; the abstraction component retrieves and processes data; and the control component is the middleman between presentation and abstraction which manages the flow of information and the communication between these components. Unlike MVC, where a view talks directly to a model, PAC's presentation and abstraction never talk directly to each other and the communication between them is mediated by control. Unlike Django which follows the MVC pattern, the popular content management system Drupal follows the PAC pattern.

Django's MVC

Although Django adopts the MVC pattern, it is a little bit different from the standard definition. Namely that,

  • In Django, a model describes what kind of data gets stored on the server. So, it's similar to a standard MVC pattern's model.
  • In Django, a view describes which data gets returned to the users. While a standard MVC's view describes how the data is presented.
  • In Django, a template describes how the data gets presented to the users. So, it's similar to a standard MVC pattern's view.
  • In Django, a controller defines the mechanism provided by the framework: the code that routes a incoming request to an appropriate view. So, it's similar to a standard MVC pattern's controller.

Overall, Django diverges from the standard MVC pattern because it suggests that a view should include business logic instead of only presentation logic as in the standard MVC, and that a template should take care of the majority of the presentation logic while the standard MVC does not include a template component at all. Due to these differences of Django's design compared to the standard MVC, we usually call Django's design Model-Template-View + Controller where Controller is often omitted because it's part of the framework. Therefore, most of the time Django's design pattern is called MTV.

Although it's helpful to understand the design philosophy of Django's MTV pattern, at the end of the day the only thing that matters is getting the job done and Django's ecosystem provides everything geared towards programming efficiency.

Creating Models

Since the new Django application is a blog, we are going to write two models, Post and Comment. A Post has a content field and a created_at field. A Comment has a message field and a created_at field. Each Comment is associated with a Post.

Next, modify the INSTALLED_APP tuple in myblog/settings.py to add myblog as an installed application.

Now, you should be able to execute the following command to see what kind of raw SQL will be executed when you run syncdb. The command syncdb creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created yet. Behind the scenes, syncdb outputs raw SQL statements into the backend database management system (MySQL or PostgreSQL in our example).




The SQL dump looks good! Now, you can create the tables in the database by executing the following command.

Notice that two tables, myblog_post and myblog_comment, are created in the previous command.

Have fun with the new models

Now let's dive into the Django shell and have fun with our brand new models. To run our Django application in interactive mode, type the following command:

The interactive shell opened by the previous command is a normal Python interpreter shell in which you can freely execute statements against our Django application.

Now we're familiar with the new Post model, how about using it side-by-side with the new Comment. A Post can have multiple Comments while a Comment can have only one Post.

So far, we know how to create, save and retrieve Post and Comment using existing attributes of each model. How about querying the database to find the posts and comments we want? It turns out that Django provides a slightly peculiar syntax for querying. Basically a filter() function accepts arguments who conform to the form "[field]__[field_attribute]__[relationship]=[value]". For example,

Did you notice something odd about the last two queries? Isn't it strange that m.Post.objects.filter(comment__message__startswith='This is a') and m.Post.objects.filter(comment__message__startswith='This is a', comment__created_at__lt=timezone.now()) return two Post instead of one? Let's verify what posts have been returned.

Ah hah! posts[0] and posts[1] are the same post! How did that happen? Well, since the original query is a join query of Post and Comment and there are two Comment satisfying the query, two Post objects are returned. So, how do we make it so that only one Post is returned? It's simple, just append a distinct() to the end of the filter():

Summary and suggestions

In this article, we wrote two simple models Post and Comment for our blog website. Instead of writing raw SQL, Django provides a powerful and easy-to-use ORM that allows us to write succinct and easy-to-maintain database manipulation code. Instead of stopping here, you should dive into the code and run python manage.py shell to interact with the existing Django models. It's a lot of fun!

About The Author