Content: Blog


How to Build a Website and Blog with django CMS, Without Knowing Python/Django - Pt. 8

Angelo Dini

April 11, 2016


Part 8: Creating Your First Django Application

In this part, we’ll cover how you can add a new Django app to your existing project, which will extend the basic CMS “Page” with two additional “Extra settings”:

  • Subtitle - for displaying a subtitle underneath our header.
  • Background Image - for displaying a custom background image in our header.

This change will enable us to set a title, subtitle and custom header background image directly from the Page settings and keeps our content clean, as shown in the example below:

To get started, open the Divio App and click on "Divio Shell":

This will open a shell session with all the proper configurations loaded for you, as described in the Part 7. Whenever you want to create an addon, use this button:

Next, navigate to your project folder inside the Divio workspace directory:

cd <project-name>

Replace “<project-name>” with the project name (slug), which is the name of your project in lower case separated by dashes.

Make sure "Auto-sync" is disabled. Inside the project directory, use the following command to create a new Django application:

docker-compose run --rm web python startapp my_custom_page_extension

This command will generate a Django application located in “<your_project_directory>/my_custom_page_extension.” You can open your projects directory by running:

open .

A finder window will open with the current directory from within the shell:

The following files are automatically created for you: This (empty) file is used to mark directories as Python package directories. Contains instructions for the Django admin site on how this application’s models are handled.
migrations/ Database migrations for the application. Description of data in the database, represented as Python code. Application-specific test cases. View functions for your application.

If you don’t understand what each files does, don’t worry. We’ll cover the relevant aspects shortly, with example code and details in info boxes.

Setup the application

The django CMS is a highly extensible software. It allows you to create/extend custom Page or Title models, dynamic CMS Addons, but also defines custom Toolbar behaviours. 

To get started, head back to your favourite editor and open the local project now.

Once you have everything set, open “my_custom_page_extension/” and replace the entire contents with the following code:

from django.db import models

# page extension imports
from cms.extensions import PageExtension
from cms.extensions.extension_pool import extension_pool

# django filer imports
from filer.fields.image import FilerImageField

class PageFieldExtension(PageExtension):
    subtitle = models.CharField(max_length=255, blank=True)
    background_image = FilerImageField(blank=True)


Django Models
Django models are descriptions of how data is stored in the database as code. Traditionally, you would create the database structure through SQL commands or a UI tool such as phpMyAdmin. Django does this through your code. Let’s have a look at an example:

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    birthday = models.DateField()

This code tells your database to create a table “Person” with three fields named “first_name,” “last_name” and “birthday.” Each of the columns can have certain properties. “First_name,” for example, is a “Character Field” that allows you to store up to 50 characters. There are many more options available.

Save the file and create a new one named “” inside “my_custom_page_extension.” Copy and paste the following code in there:

# page extension imports
from cms.extensions.toolbar import ExtensionToolbar
from cms.toolbar_pool import toolbar_pool

# import our model from ````
from .models import PageFieldExtension

class PageFieldExtensionToolbar(ExtensionToolbar):
    # loads the modal from ````
    model = PageFieldExtension

    def populate(self):
        # setup the extension toolbar with permissions and sanity checks
        current_page_menu = self._setup_extension_toolbar()
        # if it's all ok
        if current_page_menu:
            # retrieves the instance of the current extension (if any)
            # and the toolbar item URL
            page_extension, url = self.get_page_extension_admin()
            if url:
                # adds separator
                # adds a toolbar item
                    'Extra settings',
                    disabled=not self.toolbar.edit_mode,

Toolbar API
The django CMS toolbar is a core part of the user experience. Because of this, it provides an extensive API to add, modify and remove menu and button entries. This can be as simple as a link to an external website or complex entries that change their behaviour, according to your actions.

Next, open “my_custom_page_extension/” and replace its contents with:

from django.contrib import admin

# page extension imports
from cms.extensions import PageExtensionAdmin

# import our model from ````
from .models import PageFieldExtension

class PageFieldExtensionAdmin(PageExtensionAdmin):
    pass, PageFieldExtensionAdmin)

Django Administration
Creating models as described in “Django Models” is just one step. The next requires you to register it to the administration in order to be editable as a user. Django admin is very powerful and provides automatic display and validation, according to their properties. Take a look at:

first_name = models.CharField(max_length=50)

In this example, Django will automatically recognise the character field as a text input: “<input type=”text”>” and adds the necessary restrictions: “<input type=”text” maxlength=”50”>.” Furthermore, the admin provides a nice user interface to display the fields.

Now you need to add our application to Django’s “INSTALLED_APPS” section. Open up “/” inside the project root and replace:

    # add you project specific apps here

with the following code:

    # add you project specific apps here

Next, we need to create database migrations for our application, so Django knows which tables and fields need to be added to the database.

Enter the following command into your terminal:

docker-compose run --rm web python makemigrations my_custom_page_extension

This command will prepare all “migrations” defined in our Django models.

Follow up with:

docker-compose run --rm web python migrate my_custom_page_extension

This command will take the prepared migrations and apply them to the database. Be sure to check the output from your console. There should be no error as shown in the image above.

Django Migrations
Writing a model in “” does not automatically create the tables and fields in your database. You first need to create a schema using “makemigrations” that will track changes over time.

As your application evolves, so does your data. Most code changes in “” require you to create new migration schemas through “makemigrations.” This ensures that changes are tracked over time and your data stays intact.

Finally, you need to run “migrate” to apply these changes to the database. While “makemigrations” creates schema files in the “migrations/” folder, “migrate” applies those changes to the database.

Now go to your website and reload. 

Tip: if you closed the Browser and need the URL again, simply click on the "eye" icon again on your "Local Server". 

Open the toolbar by appending “/?edit” to the URL and “Log in as…” your user.

Click on “Page” and you will see a new entry called “Extra settings” – the one we added just a few moments ago. Click on the menu entry and add a subtitle and example image of your choice.

Before we can see the result of our new app, we have to adapt the Django templates for it. 

Head back to your editor and open “/templates/base.html.” Replace the first line:

{% load staticfiles i18n cms_tags sekizai_tags menu_tags %}

with the following code:

{% load staticfiles i18n cms_tags sekizai_tags menu_tags thumbnail %}

Next, search for:

{% placeholder header or %}
    <!-- Set your background image for this header on the line below. -->
    <header class="intro-header" style="background-image: url({% static 'img/about-bg.jpg' %})">
        <div class="container">
            <div class="row">
                <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                    <div class="page-heading">
                        <h1>{% page_attribute "page_title" %}</h1>
{% endplaceholder %}

and replace the code with:

<!-- Set your background image for this header on the line below. -->
{% render_model_block request.current_page.pagefieldextension %}
<header class="intro-header" style="background-image: url(
    {% with image=request.current_page.pagefieldextension.background_image %}
        {% if image %}
            {% thumbnail image 1200x400 crop subject_location=image.subject_location %}
        {% else %}
            {% static 'img/about-bg.jpg' %}
        {% endif %}
    {% endwith %}
    <div class="container">
        <div class="row">
            <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                <div class="page-heading">
                    <h1>{% render_model request.current_page "page_title" %}</h1>
                    {% if request.current_page.pagefieldextension.subtitle %}
                        <hr class="small">
                        <span class="subheading">
                            {{ request.current_page.pagefieldextension.subtitle }}
                    {% endif %}
{% endrender_model_block %}

After saving these changes, reload the page again and you should see now the background image and subtitle you defined before:

If you want to change the default page title, head to “Page” followed by “Page settings” and fill in “Page title” with your desired title. This information will be different from what is displayed in the menu or page tree and serves specifically to set our heading title. 

“Publish changes” to wrap things up.

You now have a working header in your local example. Let’s publish to the live site. For this, simply run:

git add -A && git commit -am "added page extension" && git push

followed by:

divio project push db && divio project push media

Type in “y” and hit enter when prompted to proceed.

Version Control
Divio Cloud is tracking all changes using Git, a widely used source code management system for software development. It’s a distributed revision control system with an emphasis on speed, data integrity and support for distributed, non-linear workflows.

Head back to the Divio Control Panel, select your site and choose “Deploy” on the "Test Server" for the changes to take effect. Once the deployment has concluded, open the site.

You’ve now successfully pushed your local changes to the cloud, including database, media and static files. This enables you to work locally, make all required changes and publish to the cloud once you are ready.


Jump to Index   Part 9: Creating Your First django CMS Plugin


blog comments powered by Disqus

Want to post your article here?

Contact us