A post is like a page but while a page may exist by itself a post is always assigned to a page and cannot exist by itself without a page as its parent.

Usually many posts are assigned to the same page.

This pattern can be found in many different scenarios such as blog posts, services, case studies, news articles etc.

In order to use posts, a new type of post must be declared first. We will create a new class describing news articles. The idea is that we can then assign all news articles to a particular News page that is dedicated to list all news – although there is no reason why you could not have multiple pages that are hosting news posts.

from cubane.cms.models import Post

class NewsArticle(Post):
    class Meta:
        ordering = ['-published_on']

    def get_form(cls):
        from myapp.forms import NewsArticleForm
        return NewsArticleForm

The model is declared like a page but derived from cubane.cms.models.Post instead of cubane.cms.models.BaseAbstract. The default ordering is based on published_on, so that newest articles are naturally presented first.

Like a page, the news article model also requires the declaration of a corresponding form:

from cubane.cms.forms import PostForm

class NewsArticleForm(PostForm):
    class Meta:
        model = NewsArticle
        fields = '__all__'

And that’s it. The content management system will automatically generate the corresponding sections in the backend system to manage news articles.

In order to use them, at least one page needs to be created and configured to host news articles. Once this has been done, any number of news articles can be assigned to such page.

See also

Posts share most properties of regular pages. Please refer to section Pages for more information about pages.

Post Listing

When rendering a page, a number of additional template variables will be made available automatically if the page has one or more posts assigned to it:


A queryset describing a list of all posts that are assigned to the current page and are not disabled.


A default pagination object that provides a paged view onto all posts that are assigned to the current page. Pagination options such as page size can be configured through the backend system by content editors.


The name of the underlying post class as a slug value. This may be used in combination with the {% posts %} template tag as part of the cms_tags template library as described in this section.

The template tag {% posts %} can render a list of all posts (if any) as a paginated list of records. If the {% posts %} template tag is used then a new template file must be created that matches the name of the corresponding post class (as a slug):


Replace the term <post_slug> with the slug of the name of the class that represents a post. Then the template should render a paginated list of items. For example, if slug for our class NewsArticle is newsarticle, therefore we would need to create the following template file:


The base template cubane/cms/posts/base.html can be extended to simplify the structure:

{% extends 'cubane/cms/posts/base.html' %}
{% load media_tags %}

{% block listing %}
   {% if posts %}
       <div class="posts">
                   {% for post in posts %}
                           <a class="post" href="{{ post.url }}" title="{{ post.title }}">
                           <div class="post-title">{{ post.title }}</div>
                   <div class="post-excerpt">{{ child_page.excerpt }}</div>
               {% endfor %}
   {% endif %}
{% endblock %}

The base template renders markup related to pagination while the listing block can be overridden in order to customise the structure of each post.

Usually, a link is rendered for each post, containing the title and a short excerpt text.


You do not necessarily have to follow this pattern, but keep in mind that content editors can configure via the CMS settings if and how the listing for a particular type of posts is paginated and your solution should respect such configuration.

Post URLs

The URL of a post is the combination of the slug of the corresponding page and the post itself. For example, if the page has the slug news and a particular post has the slug my-first-post then the resulting URL for the post is:


Please note that changing page ownership for a post consequently changes the URL of the post.

The URL pattern is different if the hosting page is the homepage: Then the resulting URL for the post with the slug my-first-post is:


You cannot create two posts with the same slug that are assigned to the same page. Also, if the assigned page is the homepage, the slug cannot match any existing page either.

Posts in Navigation

The navigation system provides a mechanism by which posts can also be integrated into the navigation system. Please refer to section Navigation Item Posts for more information.