Django Blog Project #1: Creating a basic blog



This is my OLD blog. I've copied this post over to my NEW blog at:

http://www.saltycrane.com/blog/2008/05/django-new-blog-project/

You should be redirected in 2 seconds.



It's been a while since my last post on Django. I became very busy but also found the Django tutorial to be somewhat dry. Luckily, the official Django Book was published during this time and it is more interesting to read. This post will be a very brief summary of the first 6 chapters of the Django Book as I apply it towards the creation of a new blog website. I highly recommend reading the book (I forgot to mention it is available free online). Then after reading the first six chapters, I hope this post can serve as kind of a refresher on how to put everything together.

As I mentioned, I decided to create my own blog site as my first Django project. I know it is not the most original idea in the world, but I thought it would be useful and a good learning experience. The following steps are my first cut at my new blog (dubbed 0.0.1) and basically just document the basic concepts of Django without providing much actual functionality.

I develop a model, a template, and a view in accordance with Django's MTV (see also MVC) development pattern. The model is of a blog post (aptly named Post) and contains only one attribute, the post body data (i.e. the actual text of the post). I should add in other data such as the title, date, tags, etc. But in order to keep things simple this first time around, it just has the post body. The model is connected to a SQLite database and is updated using Django's excellent admin interface. Finally, the model data is combined with a very basic template which just displays a title (My New Blog Version 0.0.1), and all the blog post bodies separated by a <hr>. Like I said, it's not very useful at this point, but I think I understand the basic concepts and how to put everything together much better now. The next step in my Django development will be to create some more interesting templates and views and add more useful data like titles and dates.

I also have a couple of related plans:

  • Set up hosting: I've decided to use WebFaction for my hosting but I need to set up and upload my new, almost-website there. This will probably be the subject of my next Django post.
  • Copy my Blogger posts over to my new site. I've already figured out how to use Beautiful Soup to screen scrape my Blogger posts and import them into SQLite. Likely I will do this further on in the process.

Here are the steps I took for my first cut at my new blog. Note, I'm running on Ubuntu so that's why I have the $ bash prompt and use /home/sofeng paths in my examples.

Create a new project

The first thing to do after installing Django is to create a new project. Luckily, it takes just one command to create the project.

  1. Create a new project
    $ cd ~/src/django
    $ django-admin.py startproject myblogsite
  2. Take a look at the site using the development server
    $ python manage.py runserver
    Then go to http://127.0.0.1:8000
Set up the Django admin interface

At first I thought the admin interface was kind of boring. However, for my blog site, I will use the admin interface to enter new blog posts.

  1. Edit myblogsite/settings.py to add the admin application to the list of installed apps:
    INSTALLED_APPS = (
       'django.contrib.auth',
       'django.contrib.contenttypes',
       'django.contrib.sessions',
       'django.contrib.sites',
       'django.contrib.admin',
    )
  2. Install database tables for the admin interface:
    $ python manage.py syncdb
    At this point I was asked to create a superuser to log into the admin interface. I answered "yes" and filled in the appropriate information.
    Creating table auth_message
    Creating table auth_group
    Creating table auth_user
    Creating table auth_permission
    Creating table django_content_type
    Creating table django_session
    Creating table django_site
    Creating table django_admin_log
    
    You just installed Django's auth system, which means you don't have any superusers defined.
    Would you like to create one now? (yes/no): yes
    Username (Leave blank to use 'sofeng'): sofeng
    E-mail address: sofeng@sofeng.com
    Password:
    Password (again):
    Superuser created successfully.
    Installing index for auth.Message model
    Installing index for auth.Permission model
    Installing index for admin.LogEntry model
    Loading 'initial_data' fixtures...
    No fixtures found.
  3. Edit myblogsite/urls.py to include the admin url.
    from django.conf.urls.defaults import *
    
    urlpatterns = patterns('',
       (r'^admin/', include('django.contrib.admin.urls')),
    )
  4. Run the development server:
    $ python manage.py runserver
    Then go to http://127.0.0.1:8000/admin Log in and take a look around.
Set up the SQLite3 database

I chose SQLite because it is a lightweight, simple alternative to MySQL or PostgreSQL. This makes it great for a development website.

  1. Edit the following section in the myblogsite/settings.py file:
    DATABASE_ENGINE = 'sqlite3'
    DATABASE_NAME = '/home/sofeng/src/django/myblogsite/mydatabase.sqlite3'
    The rest of the DATABASE_ variables are not used with SQLite.
  2. Test out the database configuration: Run the shell:
    $ python manage.py shell
    Then type these commands:
    >>> from django.db import connection
    >>> cursor = connection.cursor()
    If nothing happens, all is good. See Table 5-2 in Chapter 5 of the Django Book common database configuration error messages.
Create an App

I think of an "app" as a piece of specific functionality of a website, whereas a project corresponds to a particular website. There can be many apps in a project. Also, apps can be used in more than one project. For more information about the differences between projects and apps see Chapter 5 of the Django Book.

  1. Create an app
    $ cd ~/src/django/myblogsite
    $ python manage.py startapp myblogapp
Create a Model

I created one model, the Post model. A model roughly corresponds to a SQL table. And each attribute in that model corresponds to a table row. I added the class Admin: so that my Post model would show up in the Admin interface (where I can insert the data).

  1. Edit myblogsite/myblogapp/models.py to look like the following:
    from django.db import models
    
    class Post(models.Model):
       body = models.TextField()
    
       # in the future I will add these other attributes
    #    title = models.CharField(maxlength=500)
    #    timestamp = models.CharField(maxlength=50)
    #    tags = models.CharField(maxlength=200)
    
       class Admin:
           pass
    Correction 7/6/2008: For the Post's body field, I previously used the line: body = models.CharField(maxlength=999999). However, thanks to Myles's comment in my post #4, I've changed this to use the more appropriate TextField.
Install the Model

After writing the Python model code, I needed to create the actual tables in the SQLite database. The following steps include a couple of checks, then I create the tables in the last step.

  1. Edit myblogsite/settings.py file again and add the blog app to the list of installed apps:
    INSTALLED_APPS = (
       'django.contrib.auth',
       'django.contrib.contenttypes',
       'django.contrib.sessions',
       'django.contrib.sites',
       'myblogsite.myblogapp',
    )
  2. Try validating the model:
    $ python manage.py validate
    Which gives the following message:
    0 errors found.
  3. Check the CREATE TABLE statements that Django will generate. Note, the database won't be modified.
    $ python manage.py sqlall myblogapp
    Which yields the following:
    BEGIN;
    CREATE TABLE "myblogapp_post" (
       "id" integer NOT NULL PRIMARY KEY,
       "body" text NOT NULL
    );
    COMMIT;
    Correction 7/6/2008: I've updated the results here to reflect the correction I made to the model above.
  4. Now, actually create the tables in SQLite:
    $ python manage.py syncdb
    Which yields something like this:
    Creating table blog_post
    Loading 'initial_data' fixtures...
    No fixtures found.
Create some new data using the admin interface

Now that I created the models and tied them to the admin interface, I can start adding data using the admin interface.

  1. Start the development server again:
    $ python manage.py runserver
    Go to http://127.0.0.1:8000/admin and log in.
  2. Under the "Blog" heading, click "Posts", then add some new posts using "Add post" and the "Save" links. This will add data to the SQLite database.
Create a template

Now I will display the data I just created using a template and a view. The template holds all the HTML code and some simple Django template code which the view's Python code uses to customize the page.

  1. Create the file myblogsite/templates/mytemplate.html and put the following inside:
    <html>
     <head><title>Post</title></head>
     <body>
       <h1>My New Blog Version 0.0.1</h1>
    
       {% for post in post_list %}
       {{ post }}
       <hr />
       {% endfor %}
    
     </body>
    </html>
  2. Edit myblogsite/settings.py again to instruct Django where to find the template files.
    TEMPLATE_DIRS = (
       '/home/sofeng/src/django/myblogsite/templates',
    )
    Be sure to include the comma at the end.
Create a view

The view is where I will grab the data from my model and insert it into my template.

  1. Create a new file myblogsite/myblogapp/views.py and put the following inside:
    from django.shortcuts import render_to_response
    from myblogsite.myblogapp.models import Post
    
    def myview(request):
       posts = Post.objects.all()
       post_body_list = [post.body for post in posts]
       return render_to_response('mytemplate.html',
                                 {'post_list': post_body_list})
    Correction 7/6/2008: I previously had from myblogapp.models import Post on the second line. This works, but is inconsistent with my urls.py below and can (and did for me) cause subtle errors in the future. I corrected the line to read: from myblogsite.myblogapp.models import Post.
Map an URL to the new view

Finally, I map an URL to my newly created view.

  1. Edit myblogsite/urls.py so that it looks like:
    from django.conf.urls.defaults import *
    from myblogsite.myblogapp.views import myview
    
    urlpatterns = patterns('',
       (r'^admin/', include('django.contrib.admin.urls')),
       (r'^myview/$', myview),
    )
  2. Take a look at the new page: Run the server:
    $ python manage.py runserver
    Then go to http://127.0.0.1:8000/myview Visiting the url shows all the posts I entered through the admin interface. Nice. Here is a snapshot screenshot of my new blog:

That's it for now. I tried to map out the basic steps for using Django's MTV development pattern. Hopefully, in the future, I'll be able to add more useful features to my new Django-powered blog.


Related posts:
   Install Django on Ubuntu
   Django Blog Project #2: Deploying at Webfaction
   Django Blog Project #3: Using CSS and Template Inheritance
   Django Blog Project #4: Adding post metadata
   Django Blog Project #5: YUI CSS and serving static media
   Django Blog Project #6: Creating standard blog views
   Django Blog Project #7: Adding a simple Atom feed
   Django Blog Project #8: Adding basic comment functionality

2 comments:

Abhishek said...

Hi This is Abhishek From Mumbai,India.
Its very nice post..
i have follow it to create same application but in the process as we add my admin model and the post model after that on http://localhost:8000/admin
i get login by the user and pass which we have used for the databse but i cant see any post or blog tag or label .. can you please help in this

sofeng said...

Abhishek,
Perhaps you did not add the Admin class to your Post class? Other than that, I can't think of anything.
-sofeng

About

This is my *OLD* blog. I've copied all of my posts and comments over to my NEW blog at:

http://www.saltycrane.com/blog/.

Please go there for my updated posts. I will leave this blog up for a short time, but eventually plan to delete it. Thanks for reading.