Django Tutorial: Blog Basics

 

Today we’ll be learning the gist of Django, a pythonic web framework. In the spirit of a stereotypical web framework django tutorial, we’ll produce a primitive blog with the minimal amount of code possible. Yellow background color text indicates text to be entered into a command line/terminal and blue indicates code. If you’ve followed my django screencast, you’ll be familiar with the most of what this tutorial covers. However, I’ll explain the code in this tutorial in more depth than I did in the screencast. If you like to know what everything does, this article is for you.

If you’ve never dealt with (or even seen) python code before, I recommend skimming through python’s official tutorial. The most notable difference between python and most other languages is that tabs/spaces are used to indicate code blocks. So an if statement would look something like this:

if myvariable == True:
    print “myvariable is True”
print “Always printed”

One other thing to note is that boolean variables are True and False (case-sensitive). It’s also a good idea to dust off your terminal / command line skills (cd, ls, etc.).

Table of Contents

  1. Installation

    1. Development Methodologies
  2. Getting Started

    1. Creating Our First Application
  3. Django Admin
  4. Running the Development Server

    1. Customizing Model Display
  5. Public Facing

    1. Generic Views
    2. Url Function
  6. Order By
  7. Templates

    1. Base.html
    2. Listing page
    3. Detail page
  8. Comments

    1. Listing page
    2. Detail Page
    3. Final Result
  9. Wrapping Up

Installation

If you’ve followed another django tutorial, you’re all set. Otherwise here’s some brief steps to follow.

  1. Download & Install Python 2.6 (via python’s site or apt-get)
  2. Install your database engine of choice and it’s associated python library. I use sqlite3 when developing because it’s lightweight and requires no db login information. As an added convenience, pysqlite is pre-bundled into python 2.5 and beyond.
  3. Install Django. This is can be either the latest official build or the stable (in my opinion) subversion repository. Use the svn url, http://code.djangoproject.com/svn/django/trunk/ for checkout. If you’re using a terminal/command line system, type:
    svn co http://code.djangoproject.com/svn/django/trunk/ django to download the trunk release to a django subdirectory. While in that directory, use svn upto update your repository when needed. I’ll be using the svn revision #10071, although any 1.0+ version of django should work just fine.
  4. (For windows) Add your (python path)/scripts to your windows PATH environment variable. See video if you’re unsure how to do this. You may need to reboot afterwards.
  5. If typing the django-admin.py command in your command prompt/terminal doesn’t give you a missing command/file error then you’re all set! If you prefer not to have it in your PATH variable, you’ll have to refer it via an absolute path from your python/scripts/django-admin.py.

Alternatively, you could try using a DjangoStack installer, but I’ve never used one so I can’t say how easy or hard it is.

Development Methodologies

Unless you’ve been hiding under a rock or are completely new to the web development community, you know that Model-View-Controller (MVC), is the latest craze is the web world. This provides a clean separation among:

  • Code that interfaces with data resources (usually from a database) [Model]
  • Logic for each type of page a user can visit [Controller]
  • Html or other response output to the end user [View]

Django is quite similar, although it uses the name MTV (Model-Template-View) instead. This is slightly confusing for people coming from other MVC frameworks since a MVC Controller is a View in Django and a MVC View is a Template in Django. I’ll be referring to everything in terms of Django’s MTV in the remainder of the tutorial.

Django templates have their own template language which is relatively easy to grasp for programmers. It’s catered for web designers (not programmers) to manage logic that directly deals with how to display data. The templating system is designed to be as minimal as possible and specifically excludes any feature that doesn’t relate to the display logic (e.g. variable assignments are not allowed). Although the templating system could be extended to implement such features, most of that code really belongs in the view.

For more information, you can see the entire laundry list of Django’s philosophies.



Getting Started

I prefer to run instead of walk first, but that’s just me. Let’s create a django project using django-admin.py startproject myblog to create a myblog directory containing our django project.

What are these files?

When you first create a project, you have the following files:

  • __init__.py
  • manage.py
  • urls.py
  • settings.py
__init__.py tells python that this folder is a package which can be imported/included by other python packages. This allows the django framework to import our application for execution. This file only needs to exist for this effect.
manage.py provides commands that django-admin.py provide with all the settings that are specified in settings.py. This allows you to do: python manage.py runserver to run the server for this project instead of having to add your project module to python’s module search paths and specify the settings.py file.
urls.py describes the server mapping from urls to function calls, which ultimately result in a http response. URLs are mapped via regular expressions.
settings.py contains project-related settings. This includes individual application setting parameters as well as global ones (such as database and timezone info).

We’ll edit settings.py and enter our database information:

DATABASE_ENGINE = ‘sqlite3′
DATABASE_USER = ‘sqlite.db’

Fill in other database information if your database engine requires it (which is anything other than sqlite3). You can edit your TIME_ZONE to be closest to your server location (or your location if you’re running it locally), but it doesn’t really matter too much for us.

File paths in settings.py must be absolute. This is because a relative path isn’t explicit (one of python’s philosophies) since it could refer to either where django’s site-package location (where some provided addons reside) or your current working directory (where you executed the command to start the server) or your project directory. Instead paths are all absolute. Since we’re going to make all our relative paths relative to the project directory, or settings.py to be more precise, we’ll add the following code snippet to the top of our settings.py to automatically convert all our relative paths we specify to absolute paths.

import os
rel = lambda *x: os.path.join(os.path.abspath(os.path.dirname(__file__)), *x)

The first line imports the python-provided os module which provides us with path-related functionality.

The second line is a bit more complicated to gobble. We’re creating a lambda/anonymous function named rel. In python, lambda functions are usually short one-liner functions that have to return a value, which also explains the reason why there’s no return keyword (the expression is implicitly returned). As part of the lambda definition, we accept any amount of arguments which is stored in array x.

We then join a series of paths (which will figure out the appropriate directory separator based on the operating system) which includes the absolute path determined by the directory name where this file resides (settings.py) and any directories we provide in the function parameters. *x expands the x array and passes to the function as parameters.

Now we can provide relative directories from our project directory. Let’s specify those now in settings.py. Make the following changes (or change them to whatever you feel is right):

MEDIA_ROOT = rel(‘media’) # media subdirectory in the project directory

MEDIA_URL = ‘/resources/’ # for the variable we get to use in templates, later
TEMPLATE_DIRS = (
    rel(‘templates’),
)

If you wanted all the media and templates in one directory you could do something like:

MEDIA_ROOT = rel(‘resources’, ‘media’)
MEDIA_URL = ‘/resources/’
TEMPLATE_DIRS = (
    rel(‘resources’, ‘templates’),
)

Save, and we’re good for now.

Creating Our First Application

What good is a blog without any posts? Our first application will provide the framework for a blog post. So in the project directory execute django-admin.py startproject posts or python manage.py startproject posts to create a subdirectory and application names posts.

What’s the difference between projects and applications?

Projects contains and provides templates for a collection of applications. Instead, applications provide specific functionality a project would need. This can be related to a traditional desktop application which houses plugins. It is highly encouraged to partition your applications as much as possible while minimizing the interdependency of applications.

The key advantage to this design is the ability to “drag-and-drop” applications from one project to another, providing features to that particular project. The project can utilize some or all of the features provided by the application.

The following files in the new directory are as listed:

  • __init__.py - same reason as the project’s __init__.py
  • models.py - contains classes that pertain to data to be stored in the database and their mapping to python as classes.
  • views.py - contains functions that the project’s urls.py can map to. They provide the “glue” to your database data and your templates.
  • tests.py - Provides a file to perform unit testing for the application.

Before we implement anything else, we should probably create the models for our app. Our post model is going to be minimalistic. So open up models.py and append the following:

from django.contrib.auth.models import User
class Post(models.Model):
    author = models.ForeignKey(User, related_name=’posts’)
    title = models.CharField(max_length=200)
    body = models.TextField()
    pub_date = models.DateTimeField(auto_now_add=True)
    up_date = models.DateTimeField(auto_now=True)

    def __unicode__(self):
        return self.title

What’s this ‘self’?

Python is explicit. So python class methods accept one extra parameter in the beginning which is the instance of the class. This is normally named self. This identical to the $this variable in php classes and using this in java (although in java, it is only required to disambiguate).

This is presents our data for our model which inherits from django’s Model class. The first line imports the django-provide User model, which adds users support for our project, including authentication and permissions. But in this case, we’re using it to associate a user who creates a post to be the author of it. The named key parameter related_name is the variable name the User model should have to store the list of posts. By default it is <model_name>_set, but here we’re specifying it as posts.

Each post will have a title field which is a database char field whose max length is 200. This is validated both via the database (assuming you use Django to create the tables) and by Django when the model is saved. The body field is self explanatory, create a field to store a large string of text. Pub_date and up_date store datetime fields in the database. The auto_now_add keyword parameter sets the field to the current date time when the model is being added to the database (not when saving changes). Likewise, auto_now applies the current datetime whenever the model is saved.

Finally, we have a __unicode__ method defined. This is simply a unicode string to return when a post instance is requested to be displayed automatically.

That’s all the models we need! :)

Next, we’ll need to add our application to our project. Add the following line to your INSTALLED_APPS variable in settings.py:

‘posts’, # whatever you named your application

So you INSTALLED_APPS should look something like this:

INSTALLED_APPS = (
    ’django.contrib.auth’,

    ’django.contrib.contenttypes’,
    ’django.contrib.sites’,
    ’posts’,
)

It is worth noting that applications are loading in order they are listed. So your applications should always be at the end since they’ll usually depend on Djangos’ built-in applications.

Why can’t django just autoload applications?

Django could, but that imposes an efficiency issue. Frameworks become bloated when features are loaded: adding unnecessary time to load unused modules. This also goes against Django’s philosophy that everything should be interchangable with third-party modules, including modules that consist of the core of Django, such as the Templating system.

We can tell Django to create all the tables in INSTALLED_APPS based on what the models defined. This can be done with python manage.py syncdb.

The Django Syncdb Flaw

There’s one problem about manage.py syncdb: it doesn’t do schema migrations. This means that syncdb only creates non-existant tables. If the table already exists, django syncdb will do nothing. This causes problems if you want to make changes to your model & table. The simplest method is run python manage.py reset <appname> to drop and recreate tables for a particular application, but you loose all the data stored in those tables. Alternatively, there are various third-party implementations of schema migration in the works with the Django developers keeping a keen eye on them for inclusion into django.contrib. But until then, there’s no official migration method.

When creating tables for django.contrib.auth, it asks you to create a superuser, do so since it’ll allow you to login in the admin interface we’ll be discussing in the next section.

We will be continuing Part II tomorrow so stay tuned by subscribing to the RSS Feed

Be Sociable, Share!

Written by Brenley Dueck

 

34 Responses to “Django Tutorial: Blog Basics”

  1. links for 2009-03-31 « Bloggitation Says:

    March 31st, 2009 at 2:03 am

    [...] A Detailed Django Tutorial: Blog Basics Part I (tags: python django web programming blog) [...]

  2. Django Blog Tutorial | Blog of Jeff Says:

    April 1st, 2009 at 10:08 am

    [...] Part 1 [...]

  3. joel Says:

    April 11th, 2009 at 11:32 am

    DATABASE_USER = ‘sqlite.db’ should be:

    DATABASE_NAME = ‘sqlite.db’

  4. joel Says:

    April 11th, 2009 at 3:04 pm

    django-admin.py startproject posts or python manage.py startproject posts

    should be startapp. i’m guessing your brother didn’t actually work through the tutorial…

  5. Jim Smiley Says:

    May 25th, 2009 at 12:13 am

    HI,
    I am having trouble understanding the model.py.
    It refers to User, and I don’t know what User looks like.
    Any help pleas

  6. v "712" jayant Says:

    June 1st, 2009 at 2:15 am

    yes joel is right. your brother has made you fool, haha. nice tutorial btw :)

  7. scott Says:

    June 9th, 2009 at 9:55 pm

    Creating Our First Application

    What good is a blog without any posts? Our first application will provide the framework for a blog post. So in the project directory execute django-admin.py startproject posts or python manage.py startproject posts to create a subdirectory and application names posts.

    ITs not STARTPROJECT its STARTAPP

  8. Jeff Says:

    June 14th, 2009 at 5:22 pm

    Sorry about being late. (There really needs to be some email notifications via comments).

    Yeah, due to some miscommunication, my brother actually didn’t read through the whole thing before I published it. My bad :(

    Thanks joel and scott for pointing out the typos.

  9. Bubs Says:

    August 18th, 2009 at 3:38 pm

    Hi,

    Nice tutorial… Thanks!

    For future noobs that do not read comments first, it might be good if you fix your tutorial to say “startapp” vs. “startproject”. That took me a few to figure out due to my noobiness.

  10. nick Says:

    October 10th, 2009 at 9:20 am

    Another problem with this article is that all the single quotes have been changed to apostrophes, which breaks all the code.

    Why don’t you fix these problems in your posts rather than just acknowledging them in the comments?

  11. By: nick « Python Developer India Says:

    October 11th, 2009 at 11:51 pm

    [...] See the article here: By: nick [...]

  12. Evgeniy Says:

    October 21st, 2009 at 11:58 pm

    In advance, sorry for my english.
    Congratulations on the article.

    Can I bookmark this and then mention it on my blog?

  13. Brenley Dueck Says:

    October 22nd, 2009 at 9:19 am

    go for it!

  14. xyan Says:

    December 14th, 2009 at 12:40 am

    …So in the project directory execute django-admin.py startproject posts or python manage.py startproject posts …. should be
    python manage.py startapp posts

  15. Dave Says:

    March 3rd, 2010 at 4:07 pm

    I’d say great tutorial but I am wary of following it due to not wanting to waste my time if there are so many issues on the first page, I am wondering what it’s going to be like later on??

    Also, I agree with folks before me – if someone points out issues, some glaring ones at that, doesn’t it make sense to correct them in the post? Seems to go against the whole point of posting a tutorial if you don’t fix the mistakes.

    Sorry to be negative. Really appreciate that you’ve put this up for us all but if you’re going to do it, do it right :)

  16. Jeff Terry Says:

    March 6th, 2010 at 1:42 pm

    Thanks for this post. I am new at python and this will help a lot.

  17. Angela Jones Says:

    March 6th, 2010 at 5:30 pm

    Cool Thanks for your post. I am starting django and this got me straight.

  18. Marlo Noval Says:

    March 19th, 2010 at 11:59 am

    I used the Django 1.1.1 and this line
    DATABASE_USER = ’sqlite.db’
    must be
    DATABASE_NAME = ’sqlite.db’

    ;)

  19. Shopping Spree Says:

    March 23rd, 2010 at 11:41 am

    You could have a excellent method of placing elements into viewpoint.

  20. Shandalf Says:

    April 3rd, 2010 at 9:59 am

    “Why don’t you fix these problems in your posts rather than just acknowledging them in the comments?”

    This.

  21. A Roundup of 10 Django Tutorials | blogfreakz.com Says:

    May 19th, 2010 at 3:03 am

    [...] 5. Brenelz: A Detailed Django Tutorial [...]

  22. Abe Says:

    June 4th, 2010 at 9:34 am

    For future readers, could you correct the errors in this post? I can easily imagine some people banging their heads against a table for hours trying to work through some of the errors here.

  23. Ankara Says:

    July 14th, 2010 at 2:15 am

    below line returs with error on Eclipse.

    author = models.ForeignKey(User, related_name=’posts’)

  24. javavs vb Says:

    August 12th, 2010 at 6:18 am

    What exactly is better programming language to start off with java or vb?

  25. {Pixels Space} » Blog Archive » learn Django from the web Says:

    September 23rd, 2010 at 4:01 am

    [...] Bernelz – Detailed Django tutorial – blog basics: Again, a four part tutorial that teaches one how to create a basic blog site using Django. This [...]

  26. 討債 Says:

    December 8th, 2010 at 5:47 am

    To solve these cases, where you would like to assign empty strings to the extra variables (and eliminate errors), append a delimiter string to the string as follows.

  27. Calgary Design Says:

    December 15th, 2010 at 11:44 pm

    Hey, great post. I’ll definitly be bookmarking this.

  28. Salvatore Doxon Says:

    January 4th, 2011 at 5:14 pm

    I was just thinking about that, hmm interesting I wonder. Well thanks for the post really handy, to me anyway.

  29. video games Says:

    April 14th, 2011 at 10:37 am

    What exactly is better programming language to start off with java or vb? Can we build facebook sites off of this?

  30. Jurij Ghirin Says:

    May 12th, 2011 at 5:48 am

    Hi!
    Thanks for a good article. By the way: is it an error in ”
    We’ll edit settings.py and enter our database information:

    DATABASE_ENGINE = ‘sqlite3′
    DATABASE_USER = ‘sqlite.db’ <<<HERE?"
    AFAIK it should be empty for sqlite3.
    Correct me if I am wrong.

    Thanks!

  31. AusweisApp Says:

    September 6th, 2011 at 2:24 pm

    I think Jurij Ghirin is right – leave it empty and it will work!

  32. A Roundup of 10 Django Tutorials | codeManiac - Snippets, Templates, API and the best developer content Says:

    April 29th, 2012 at 4:04 pm

    [...] 5. Brenelz: A Detailed Django Tutorial [...]

  33. Franziska Says:

    November 26th, 2012 at 11:27 pm

    It’s great that you are getting thoughts from this post as well as from our dialogue made at this time.

  34. felix Says:

    March 12th, 2013 at 1:22 am

    good work…….

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 
connect with me!