How to create a Blog application¶
A Blog is made of dated Blog Posts. It so happens this CMS pages model contain a creation date and is flexible enough to contain all sort contents that could be useful in a Blog post. So how can we use this CMS to create a Blog application? This guide gives a step by step recipe that demonstrate how easily you can build new features on top of this CMS.
Step 1: Create a new Django app within your project¶
python manage.py startapp blog
Step 2: Create the views¶
Open you newly created blog/views.py file and create 2 views. One for the category view and another for the Blog’s index. We are using the django-taggit application to handle the categories, this way a Blog Post can be included in several categories.
from django.shortcuts import render
from pages.models import Page
from taggit.models import Tag
from django.core.paginator import Paginator
def category_view(request, *args, **kwargs):
context = dict(kwargs)
category = Tag.objects.get(id=kwargs['tag_id'])
page = context['current_page']
blogs = page.get_children_for_frontend().filter(tags__name__in=[category.name])
paginator = Paginator(blogs, 8)
page_index = request.GET.get('page')
blogs = paginator.get_page(page_index)
context['blogs'] = blogs
context['category'] = category.name
return render(request, 'blog-home.html', context)
def blog_index(request, *args, **kwargs):
context = dict(kwargs)
page = context['current_page']
blogs = page.get_children_for_frontend()
paginator = Paginator(blogs, 7)
page = request.GET.get('page')
blogs = paginator.get_page(page)
context['blogs'] = blogs
context['template_name'] = 'blog-home.html'
return render(request, 'blog-home.html', context)
Step 2: Link the views with the CMS¶
Populate blog/urls.py with those urls
from django.conf.urls import url
from blog import views
from django.urls import include, path, re_path
urlpatterns = [
url(r'^category/(?P<tag_id>[0-9]+)$', views.category_view, name='blog_category_view'),
url(r'^$', views.blog_index, name='blog_index')
]
Then the last step is to register this URL module with the CMS. Place this code at the top of you project urls.py file.
from pages.urlconf_registry import register_urlconf
register_urlconf('blog', 'blog.urls', label='Blog index')
Step 3: Create the blog templates¶
You will need create 3 templates for your blog application. The first one is a helper template called blog-card.html. It contains a basic representation of a blog as a card:
{% load pages_tags static i18n humanize thumbnail %}
<div class="card mb-4 shadow-sm">
<a class="blog-lead-image" href="{% show_absolute_url page %}">
{% get_content page "lead-image" as image %}
{% if image %}
{% thumbnail image "320x240" crop="center" as img %}
<img src="{{ img.url }}">
{% endthumbnail %}
{% else %}
<!-- no image for this post -->
{% endif %}
</a>
<div class="card-body">
<a href="{% show_absolute_url page %}">
<h3 class="my-0 font-weight-normal">{% show_content page "title" %}</h3>
</a>
<p>{% show_content page "lead" %}</p>
{% if forloop.first %}
{% get_content page "content" as content %}
<p class="d-none d-lg-block">{{ content | striptags | safe | truncatechars:220 }}</p>
{% endif %}
<p class="blog-meta">Published {{ page.creation_date | naturalday }}
{% if page.tags.count %}
in the categories:
{% for tag in page.tags.all %}
<a href="/{{ lang }}/blog/category/{{ tag.id }}">{{ tag.name }}</a>{% if not forloop.last %},{% endif %}
{% endfor %}
{% endif %}
by {{ page.author.first_name }} {{ page.author.last_name }}
</p>
</div>
</div>
The second is the blog-home.html referenced by the views you previoulsy wrote, it will be used by the index and the categories:
{% extends 'index.html' %}
{% load pages_tags static i18n humanize thumbnail %}
{% block header %}
<div class="px-3 py-3 pt-md-5 pb-md-4 mx-auto text-center">
<h1 class="display-4">{% placeholder "title" %} {{ category }}</h1>
<p class="lead">{% placeholder "lead" with Textarea %}</p>
</div>
{% endblock %}
{% block content %}
<div class="card-deck mb-3 text-center blog-home">
{% for page in blogs %}
{% include "blog-card.html" %}
{% endfor %}
</div>
<div class="pagination">
<span class="step-links">
{% if blogs.has_previous %}
<a href="?page=1" class="btn btn-light">« first</a>
<a href="?page={{ blogs.previous_page_number }}" class="btn btn-light">previous</a>
{% endif %}
<span class="current">
Page {{ blogs.number }} of {{ blogs.paginator.num_pages }}.
</span>
{% if blogs.has_next %}
<a href="?page={{ blogs.next_page_number }}" class="btn btn-light">next</a>
<a href="?page={{ blogs.paginator.num_pages }}" class="btn btn-light">last »</a>
{% endif %}
</span>
</div>
{% endblock %}
Finaly the last one is for the Blog Post itself. You could have different Blog Post templates but for now we only need one, let’s call it blog-post.html:
{% extends 'index.html' %}
{% load pages_tags static i18n humanize %}
{% block header %}
<div class="px-3 py-3 pt-md-5 pb-md-4 mx-auto text-center blog-post">
<h1 class="display-4">{% placeholder "title" %}</h1>
<p class="lead">{% placeholder "lead" with Textarea %}</p>
<p class="blog-meta">Published {{ current_page.creation_date | naturalday }}
{% if current_page.tags.count %}
in the categories:
{% for tag in current_page.tags.all %}
<a href="/{{ lang }}/blog/category/{{ tag.id }}">{{ tag.name }}</a>{% if not forloop.last %},{% endif %}
{% endfor %}
{% endif %}
by {{ current_page.author.first_name }} {{ current_page.author.last_name }}
</p>
</div>
{% endblock %}
{% block content %}
<div class="blog-post">
<div class="blog-lead-image">
{% imageplaceholder 'lead-image' block %}
{% if content %}
<img src="{{ MEDIA_URL }}{{ content }}" alt="">
{% endif %}
{% endplaceholder %}
</div>
<div>
{% placeholder "content" with RichTextarea %}
</div>
</div>
{% endblock %}
To finish things up you need to allow those 2 templates to be selected by the CMS. Add them to your PAGE_TEMPLATES setting:
PAGE_TEMPLATES = (
('index.html', 'Default template'),
('blog-post.html', 'Blog post'),
('blog-home.html', 'Blog home'),
)
Step 4: Activate the Blog in the admin¶
You can now activate the Blog in the CMS admin. To do so follow those few steps:
Create a new page named “Blog”, chose the template “Blog Home”, and the option “Delegate to application: Blog Index”.
Add a couple of child pages to this Blog Index page and chose the “Blog Post” template as their template.
The result should be a functional blog with an index page, category pages, tagging and pagination.
You are also free to create serveral Blog instances withing the CMS by repeating a version of this step. There is no restrictions.
A fully functionnal version of this Blog application is available