Django Blog Project #4: Adding post metadata
I've created a basic blog using SQLite as a backend, deployed it at a shared hosting provider, Webfaction, and added a little CSS for style. Now what? Well, while I say I've created a basic blog, I should say it's a not-quite-yet-basic blog. All it has is some text, which I call Posts, separated by <hr>
tags. The next step is to add some post metadata, such as a title, date of creation and tags.
Modify the
Post
modelTo create this new metadata, I first modified the Post
model in ~/src/django/myblogsite/myblogapp/models.py
:
from django.db import models class Post(models.Model): title = models.CharField(maxlength=500) date_created = models.DateField() tags = models.CharField(maxlength=200) body = models.TextField() def __str__(self): return self.title class Meta: ordering = ["-id"] class Admin: pass
I added new attributes: title
, date_created
, and tags
. The __str__
method is used to identify a Post
instance by its title. This is useful when working in the Administration page. The class Meta:
is used to reverse sort the Posts by "id".
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 below, I've changed this to use the more appropriate TextField
.
python manage.py syncdb
Whoops, running python manage.py syncdb
doesn't actually sync the model with the database. It is only used to initially create the database tables. To add the new columns to my table, I would have to enter the SQL commands directly. Though it is not super difficult, and would be good experience since all those hiring managers seem to want SQL experience, I took the lazy route and just replaced my database. (Not like I had much in there anyways.) For your reference, the section Making Changes to a Database Schema in Chapter 5 of The Django Book describes how to solve my problem without replacing my database.
$ cd ~/src/django/myblogsite $ rm mydatabase.sqlite3 $ python manage.py syncdb 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 Creating table myblogapp_post 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: [email protected] 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.
Oh yeah, I forgot gotta recreate my superuser.
Modify
views.py
slightlyIn versions 0.0.1 and 0.0.2 of my new blog, I passed a list of post bodies to my template. But actually, I could have just passed a list of the Post
objects and accessed the body attribute of each post in the template. This saves a line of unecessary code, and provides accessiblity to all the attributes of the Post
object. (I also factored out my blog version number from the base.html
template.)
~/src/django/myblogsite/myblogapp/views.py
:from django.shortcuts import render_to_response from myblogsite.myblogapp.models import Post def frontpage(request): posts = Post.objects.all() return render_to_response('frontpage.html', {'post_list': posts, 'VERSION': '0.0.3'})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
.Modify my
frontpage.html
templateThis is pretty self-explanatory. I access the the Post
object's attributes using the ".
" (dot).
~/src/django/myblogsite/templates/frontpage.html
:{% extends "base.html" %} {% block main %} {% for post in post_list %} <h2>{{ post.title }}</h2> {{ post.body }} <hr> <div class="post_footer">Created: {{ post.date_created }} | Tags: {{ post.tags }}</div> {% endfor %} {% endblock %}
A little CSS
In between the <style>
tags in ~/src/django/myblogsite/templates/base.html
:
.post_footer { font-family: Verdana, Arial, sans-serif; font-size:70%; } hr { border: 0; color: gray; background-color: gray; height: 1px; }
Start development server and add a couple posts
I started the development server and added a couple of posts in the Admin site:
$ cd ~/src/django/myblogsite $ python manage.py runserver
- I visited
http://127.0.0.1:8000/admin
, logged in, and added a couple posts.
Upload to Webfaction server
pushwebf
is my alias for hg push --remotecmd /home/sofeng/bin/hg ssh://[email protected]/webapps/django/myblogsite
$ pushwebf [email protected]'s password: pushing to ssh://[email protected]/webapps/django/myblogsite searching for changes remote: adding changesets remote: adding manifests remote: adding file changes remote: added 7 changesets with 20 changes to 10 files
Deploy
Logged into Webfaction:
$ cd ~/webapps/django/myblogsite $ hg update -C 9 files updated, 0 files merged, 4 files removed, 0 files unresolved $ ~/webapps/django/apache2/bin/restart
Here is a snapshot screenshot of version 0.0.3
The live site can be viewed at http://saltycrane.com/blog/
Related posts:
Django Blog Project #1: Creating a basic blog
Django Blog Project #2: Deploying at Webfaction
Django Blog Project #3: Using CSS and Template Inheritance
Django Blog Project #5: YUI CSS and serving static media
Comments
Why use: models.CharField(maxlength=999999) when you could use models.TextField().
Myles, Because I didn't know about models.TextField()! Thanks for the tip!
Hi, I am just reading your tutorials; they are great for django noob like me. Just one thing, to jump from #3 to #4, which adding post function in the site, at least in my situation, would cause an error saying "no such column blogapp_post.title" when trying to get on the running server. I googled a solution: use python manage.py reset [blog app name], then manage.py syncdb, would solve the problem. Hope it helps.
Hello, I'm a beginner in Django-python, but it seems that there is a mistake in the news models.py. For me it doesn't work with "maxlength" but it works with "max_length". Can you explain me? Thanks for this course. Stephane