Web development
04
Excerpt or summaryYou can replace the post content in the index template with the excerpt, but we can keep it as a backup for if the excerpt is empty:
{% if post.excerpt %} <p>{{ post.
excerpt }}</p> {% else %} <p>{{ post.
post|truncatewords:3 }}</p> {% endif %}
05
Database errorIf you’ve decided to test the changes,
06
Database queryThe output will show you what the SQL code is to add the models to the database. We want to add the excerpt field specifically, which should look something like this:
“excerpt” text NOT NULL Make a note of it.
07
Alter tableTo get into the database shell and add the field, run: $ python manage.py dbshell Then we need to use an ALTER TABLE query:
08
Save the changesWe’ve removed NOT NULL as we already have entries that won’t have an excerpt, and want to make it so an auto summary can be made. Save the changes with: COMMIT; and then exit the shell with: .quit
09
Test it outNow we can test out the excerpt code – create a new post or edit an existing one to have an excerpt. If you’ve followed our steps correctly it should work; if not, you may need to do a bit of bug fixing.
Create and manage parent and child categories as a separate function of the blog
Learn how to alter the database to create posts with categories, and add them to other posts
Have automatic summaries or manually crafted excerpts for your blog posts
Create custom RSS feeds using built-in Django functions
you’ll have noticed our web server has stopped working. This is because there is no excerpt column in our database. Therefore we need to add the excerpt column. To find out how, run:
$ python manage.py sqlall blog
ALTER TABLE “blog_post”.
And then enter the code we noted down like so:
ADD “excerpt” text;
156 The Python Book
Web development
10
Category modelWe can add a model for blog categories:
class Categories(models.Model): name
= models.CharField(unique=True, max_length=200) slug = models.
SlugField(unique=True, max_length=100) parent = models.ForeignKey(‘self’, blank=True, null=True, related_
name=’child’) def __unicode__(self):
return (self.name)
This allows for parent and child categories.
11
Administrate categories We can add it to the admin site by creating a Categories section in admin.py:class CategoriesAdmin(admin.
ModelAdmin): list_display = [‘name’,
‘slug’, ‘parent’] fields = [‘name’,
‘slug’, ‘parent’] admin.site.register (Categories, CategoriesAdmin)
Before we can make categories, though, we need to create the database table:
$ python manage.py syncdb
12
Categorise the posts Similarly to what we did with the13
Database categoryLike before, we’ll find out the SQL needed to alter the table: $ python manage.py sqlall blog Which for our example returns a somewhat different code than before: “category_id”
integer NOT NULL REFERENCES “blog_
categories” (“id”) It’s an ID we’re getting, not text, from the categories table.
14
Alter table – part 2Again let’s enter the database shell:
python manage.py dbshell We’ll continue much like before, but with the new code: ALTER TABLE “blog_post” ADD “category_id”
integer REFERENCES “blog_categories”
(“id”); And finally, to save: COMMIT;
15
Administrate categories – part 2Now we can go back to admin.py and add the new category fields to the PostAdmin model:
list_display = [‘title’, ‘author’, ‘pub_date’, ‘category’] fields = [‘title’,
‘pub_date’, ‘author’, ‘post’, ‘excerpt’, ‘category’] Our previous blog posts with no category have disappeared! To fix this, go back to models.py and make this change to the Post model:
category = models.ForeignKey(Categories, blank=True, null=True) So we can now create categories separately, assign them to posts, and view posts without a category.
16
Category displayAs our urls.py in the blog directory gets all the post fields, to the index template we just add: <p>Category: {{ post.category }}</
p> And to the post template: <p>Category: {{
post_list.category }}</p>
17
Category pageFirst we need to define our category in blog/urls.py. Import Categories and then add:
def blog_categories(request, category_
id): categories = Categories.objects.
get(pk=category_id) We need the category_id to call the corresponding posts.
comments, we want to add a ForeignKey to the Post model so we can attribute a post to a category. Add this line: category = models.
ForeignKey(Categories)
And move Categories to the top of models.py.
We can now
create categories
separately
Web development
24
RSS URLsThe final step is adding the feed URL to urls.py: url(r’^myblog/feed/$’, BlogFeed()), And now your blog is now fully functional. With a bit more tweaking and theming, you can get it online and blog away!23
RSS linksWe need to define item_link for the feed so that the feed items can link to the right place. We have to give the complete URL and the post ID for it work: def item_link(self, post): link = “http://127.0.0.1:8000/myblog/”+str(post.pk) return link
18
Category definitionFinish the definition by using the parent_
id to filter the correct Posts, then render the response: category_posts = Post.objects.
filter(category=categories) return render_to_response(‘blog/categories.
html’, dict(category_posts=category_
posts, categories=categories)) Again we’re calling a new template that we’ll construct shortly.
19
Category URLsWe’ll create the URL in urls.py as for the post page, only it’ll give the slug of the category instead of an ID in the link: url(r’^myblog/
category/(?P<category_id>\d+/$’, ‘blog.
urls.blog_categories’),
20
Category templateWe’ll use something similar to the Index and Post template to create a category page template: {% for post in category_posts
%} <h2><a href=/myblog/{{ post.pk }}>{{
post.title }}</a></h2> {{ post.author }} on {{ post.pub_date }} % if post.
excerpt %} <p>{{ post.excerpt }}</p> {%
else %} <p>{{ post.post|truncatewords:3 }}</p> {% endif %} <p>Category: {{
post.category }}</p> {% endfor %}
21
Category clickthroughFinally, let’s make the categories click through to the relevant page by changing the
22
RSSDjango has a built-in RSS framework.In blog/urls.py add: from django.contrib.
syndication.views import Feed class BlogFeed(Feed): title = “Blog Feed” link
= “/” def items(self): return Post.
objects.order_by(“-pub_date”) def item_
title(self, post): return post.title category display to be: <p>Category: <a href=/myblog/category/{{ categories.pk }}>{{ post.category }}</a></p> This can go on the categories, post and index template.