Welcome to Molo’s documentation!

Continuous Integration Code Coverage Molo Documentation Pypi Package

Molo is a set of tools for publishing mobi sites with a community focus. It is built on top of Django and Wagtail.



Molo requires Python (version 2.6 or 2.7) to be installed. This installation method also requires pip. Both of these must be installed before following the installation steps below.

Installing Molo

Molo can be then installed using:

$ virtualenv ve
$ source ve/bin/activate
(ve)$ pip install molo.core

Getting Started

Molo scaffolds a Django application for you with sensible defaults, packages and configuration to help you get going as soon as possible.

Scaffold a site using Molo

The goal of Molo is to provide a solid base of proven, stable packages that help Praekelt Foundation and partners to deliver on project scope:

$ molo scaffold myapp
$ cd myapp/
$ ./manage.py migrate
$ ./manage.py createsuperuser
$ ./manage.py runserver

Open the sample site in your browser at http://localhost:8000/ and the CMS at http://localhost:8000/admin/.

Scaffolding a site in an existing repository

It’s not always desirable to create a new directory for an application, especially when scaffolding an application for a repository that’s already been created. Specifically for that Molo allows a second argument for the directory.

To scaffold an application called myapp in the current directory do:

$ molo scaffold myapp .

Specifying extra requires

Molo in itself is not expected to be enough to deliver on a client request. During scaffolding use the --require commandline parameter to include more libraries that are required for installation:

$ molo scaffold myapp --require=django-contrib-comments

Adds the django-contrib-comments to the generated requirements file which is read by the generated package’s setup.py file.

Multiple requires can be specified on the command line:

$ molo scaffold myapp --require=django-contrib-comments \
>   --require=molo.profiles

Automatically adding installed apps

If you’re including a Django app chances are you’re going to want to add it to your INSTALLED_APPS settings as well as adding an entry to the generated urls.py file:

$ molo scaffold myapp --include=django_comments ^comments/

This results in the following urls.py entry:



multiple includes can be specified on the command line, the format is --include=<app_name> <regex-for-urls>

For convenience, here’s the full scaffold command for the current plugins:

$ molo scaffold myapp \
    --require=molo.profiles --include=molo.profiles ^profiles/ \
    --require=django-contrib-comments --include=django_comments ^comments/ \
    --require=molo.commenting --include=molo.commenting ^commenting/ \
    --require=molo.yourwords --include=molo.yourwords ^yourwords/
Molo, Django & settings files

What you have now is a standard Django application set up for normal development like outlined in the Django documentation. The only main difference is that your settings are Python modules found in the settings/dev.py and settings/production.py files in your applications folder. Both of these inherit settings from settings/base.py.

To create your own custom settings add a local.py file in the settings folder. The settings/dev.py will automatically include those settings for your local development environment.

Unpacking Templates from Packages

Sometimes a package’s existing templates simply are not enough and need some amount of customization. Use the unpack-templates command in the scaffolded application to unpack a package’s templates in your application’s templates directory:

$ molo scaffold testapp \
>   --require=molo.profiles \
>   --include=molo.profiles ^profiles/
$ pip install -e testapp

You’ll see the default templates that molo.core ships with available in the templates directory:

$ ls testapp/testapp/templates
404.html  500.html  base.html core

Now we unpack the profiles templates directory from the molo.profiles package into the testapp package template directory:

$ molo unpack-templates molo.profiles testapp
$ ls testapp/testapp/templates
404.html  500.html  base.html core profiles

The format is:

$ molo unpack-templates <source package> <target package>
Writing tests

Now develop your application and write tests for the features you add. Running your tests for Django works as you would expect:

$ ./manage.py test

What is bundled with Molo?

  1. Wagtail CMS

  2. Basic feature phone template set.

  3. Basic models for the following tree structure:

    1. A site has a main language, and the option of one or more additional languages.
    • All content has to initially be created in the main language. Thereafter translations can be made for that content.
    • Translations for content cannot exist for additional languages if it does not first exist for the main language.
    • The first language added will be the main language, any other languages added after will be additional languages.
    1. Once a main language has been created, a main page will be created as well. A main page consists of index pages.
    • Index pages exist for each content type.
    • All section pages are grouped into the ‘Sections’ index page.
    • All banners are grouped into the ‘Banners’ index page.
    1. Once a section is made, articles can then be added to that section.
    • Articles only exist as a child of a section page.
    • Articles are composed from one or more blocks.
    • Blocks can be headings, paragraphs, images, lists or links to other pages.
    1. Content such as sections or articles are displayed in their main language. Their translation in any additional language added is shown below the content. If one would like to edit the Spanish version of ‘Staying Healthy’, one would click on ‘SPANISH’, and then edit.
    1. A Settings tab that includes Site Settings. Site Settings is where the logo, google analytics and various other settings are set.

Testing the Molo scaffolding tool

If you’re interested in working on or contributing to the code that does the scaffolding then clone this repository from the GitHub repository at http://github.com/praekelt/molo.

Install the requirement development & testing dependencies:

$ pip install -r requirements-dev.txt

And then run the full test suite with:

$ py.test

Pull requests are expected to follow Praekelt’s Ways Of Working.


Installing Plugins

Molo plugings are normal python modules and can be installed using pip:

$ pip install molo.profiles

Next, you’ll need to add the new plugin to your INSTALLED_APPS in your myapp/settings/base.py (if you did’t include it during the scaffolding step using molo scaffold myapp --include=molo.profiles ^profiles/):


Next, you’ll need to add the new plugin urls to your myapp/urls.py (if you didn’t include it during the scaffolding step using molo scaffold myapp --include=molo.profiles ^profiles/):

url(r'^polls/', include('polls.urls', namespace='molo.polls')),

The final step is to run migrations as the plugins usually have their own migrations:

$ ./manage.py migrate


Molo consists of a core structure onto which new feature plugins can be added. This core is the foundation that allows you to create a site in Wagtail.

Core Features

  • Banners
    • Image banners on the home page that can be linked to any page on the site
  • Sections (and subsections)
    • Content sections that allows structuring of content on the site
  • Articles
    • The main content element of molo.
    • It allows you to create rich articles containing multiple images, lists (bulleted/numbered) and links to other pages
  • Footer pages
    • Content pages mostly used for About, Terms and Contact information
  • Search
    • The ability to search for any content on the site
    • The ability to show a highlighted term in the results
    • Support for both Elastichsearch 1.x & 2.x


Search highlighting is only supported by the Elasticsearch backend.

You can use Elasticsearch 1 with the following settings:

    'default': {
        'BACKEND': 'molo.core.wagtailsearch.backends.elasticsearch',
        'INDEX': 'base',

Or Elasticsearch 2:

    'default': {
        'BACKEND': 'molo.core.wagtailsearch.backends.elasticsearch2',
        'INDEX': 'base',

The example below shows how to show the highlighted word in the search results page with the following rules:

  1. Title field is always displayed: if the term appears in this field, it will be highlighted.
  2. Display highlighted term in subtitle or body. If the term appears in the title only, display the original content of the subtitle field.

You need to update the search_results.html page with the following code:

{% for page in search_results %}
  {% with parent_section=page.get_parent_section ancestor=page.get_parent_section.get_ancestors.last %}
    <a href="{% pageurl page %}">
      <div class="nav">
        {% if ancestor.sectionpage.image %}
        {% else %}
        {% endif %}
        {% if page.title_highlight %}
        {% else %}
        {% endif %}
        {% if page.subtitle_highlight or page.body_highlight %}
            {% if page.subtitle_highlight %}
            {% elif page.body_highlight %}
            {% endif %}
        {% else %}
        {% endif %}
  {% endwith %}
{% endfor %}
  • Multiple Languages
    • Molo allows you to offer you content in multiple languages using the TranslatablePageMixin

Existing Plugins

The following plugins are available to extend the core features of Molo. Please see Installing plugins for installation details.


Github: https://github.com/praekelt/molo.profiles

Profiles provides user profiles which adds registration, login and user data functionality.

This library does not provide a Django user model, it provides a profile model that can be attached to a user. Our experience is that custom User models in Django add all sorts of unpleasantries when using migrations.

Main features:
  • Loging/Registration
  • User profile to store user data

Github: https://github.com/praekelt/molo.commenting

Commenting builds on the molo.profiles plugin. It allows users to comment on articles and these comments to be moderated.

It is built using Django’s Comments Framework.

Main features:
  • Commenting on article pages
  • Moderation of comments using django-admin
  • Comment reporting by users to allow for community moderation
    • COMMENTS_FLAG_THRESHHOLD allows for comments to be automatically removed if they have been reported by multiple users

Github: https://github.com/praekelt/molo.yourwords

YourWords (User generated content) allows users to submit content that can be converted into an article by an admin.

Main features:
  • Setting up a Your Words competition
  • Downloading competition entries as a CSV
  • Ability to shortlist entries
  • Converting winning entries to Articles

Github: https://github.com/praekelt/molo.polls

A poll is a short set of questions (or typically only one question) with predetermined answers that a user can choose from.

Main features:
  • Creating and publishing a Question to the home page, section page and article page
  • Multiple Question types (Single choice, Multiple Choice, Free Text, Numeric)
  • Exporting polls results as a CSV (currently in dev)

Github: https://github.com/praekelt/molo.usermetadata

User meta data allows one to create persona pages so that when a user visits a site for the first time, they are able to choose a persona, or choose to skip this. This does not require the user to log in.

Main features:
  • Creating and publishing persona pages to be displayed when the user visits the site for the first time

Multiple Languages

Molo features the ability to create translatable pages. This means that pages such as a section or article can be translatable. This is done via adding the TranslatablePageMixin in the Page’s definition.

Creating A Translatable Page Model

In your models.py import the TranslatablePageMixin:

from molo.core.models import TranslatablePageMixin

Add it to the definition of your model:

class Competition(TranslatablePageMixin, Page):
  description = models.TextField(null=True, blank=True)

Getting Translations

In order to get the translations for a page model we use the following helper functions from the TranslatablePageMixin. Given a locale, this will return the translation of the page:


We use template tags to get the locale.

The following will return the main language that the content was created in, if the content is currently in any additional language. For example, if the content is currently in French, and the main language is English, this function will return English as the main language:


Template Tags

Using template tags to get translations

In order to get the translation for a page model, we need to have the locale which is found in the context of a template. This can be accessed from a template tag.

The following template tag will return the translation for the page model. It gets the locale from the context and returns the translation for that locale:

get_translation(context, page)

Using template tags to render content

  • The load_sections template tag returns all the sections for a specific page.
  • The section_listing_homepage tag will return all the sections that are featured on the homepage.
  • The latest_listing_homepage tag will return all the articles that have been promoted to feature on the homepage.
  • The bannerpages tag will return all the bannerpages.
  • The footer_page tag will return all the foooterpages.
  • The breadcrumbs tag will return the current breadcrumbs.
  • The load_descendant_articles_for_section tag will return all the articles that are children of a section or any of its child sections.
  • The load_child_articles_for_section tag will return all the articled that are children of a section page.
  • The load_child_sections_for_section tag will return all the sub-sections that are children of a section page.

Template Patterns

Praekelt Molo Mobisite Design System

The design system will make it easy to build/scaffold custom Molo mobisites from our Python Django Molo Framework with a consistent look and feel using predefined Molo Core patterns and features - without reverse engineering our styles. The Design System and Molo Core serve as a single source of truth for our Frontend Templates stack, to help us prevent lose in translation for different mobisite applications.

Website Glossary

These are the Molo sites:

  • TuneMe

  • GEM (Girl Effect Mobile)

  • FreeBasics

  • Babycenter

  • IoGT (Internet of Good Things)

Website Components



  • Add load more functionality to section page


  • Bug Fix: Only index tag list if list not empty for sections and tags


  • Bug Fix: Only show articles in search results
  • Bug Fix: Only index tag list if list not empty


  • Bug Fix: Show translation for Section Page on Home Page
  • Bug Fix: Only show articles relevant to site under a tag
  • Bug Fix: Ensure new article tag relations are made when copying sites


  • Added Positional Banner Pages functionality
  • Bug Fix: Return Main language pages for latest articles


  • Added Tags to SectionPage
  • Added Load More functionality for ArticlePages on the homepage


  • Add gef_effective_image for ArticlePage (returns the image of article’s main language page if article has no image, else returns article’s image)
  • Add get_parent template tag (returns the parent of a page)
  • Bug fix: Filter tags via descendant of main
  • Bug fix: Use ‘to’ id directly for copying in celery


  • Bug fix: Call correct template for tag navigation
  • Bug fix: Only call translation hook for translatable pages


  • Add basics and components for Springster
  • Add tag navigation
  • Add better error handling for copying section index contents


  • Use celery for copying section index contents


  • Add parent_page_types to SectionPage


  • Fix test for admin url redirect


  • Version bump for molo profiles to resolve pin dependencies


  • Pin molo.profiles to latest version
  • Move templates out from cookiecutter
  • Implement pattern library components to templates
  • Add Mote to cookiecutter
  • Fix of previous release
  • Added index creation signals
  • Added non routable mixin for Surveys
  • Added profiles urls
  • Added multi-site cms functionality (Merged CMS)
  • Added authentication backend for linking users to sites
  • Added middleware for site redirect


  • Insure content demotion happens for each section individually


  • Remove promotion settings from footer pages


  • Fixed content import to return all data and not just default 10


  • Fixed recommended article ordering in templatetag logic


  • Added Non routable page mixin


  • Pulled in changes from previous versions that were accidentally excluded
  • Consolidated celery tasks in base settings file


  • Fixed random test failures in content rotation test


  • consolidate minute tasks into 1 call


  • Fixed bug for previewing pages


  • Excluded metrics URL from Google Analytics
  • Fixed access to Explorer bug for superuser’s with non-superuser roles


  • Allows content rotation to pick from descendant articles not only child articles


  • Updated template overrides to fix missing Page admin buttons


  • Content rotation enhancement: - Only promote pages that are exact type of ArticlePage - Only demote an article if there is more than two promoted articles


  • Add django clearsessions to celery tasks


  • Added missing classes in custom admin template


  • Fixed template error


  • Removed the ability to delete index pages using the admin UI


  • added multi-language next and recommended article feature


  • Add sitemap - include translations

Main Features:

- Upgraded to Wagtail 1.8
- Added upload/download functionality for zipped media files
- Next and Recommended articles in articles

Backwards incompatible changes

  • Deprecatad use of wagtailmodeladmin: wagtailmodeladmin package has been replaced by wagtail.contrib.modeladmin
  • wagtailmodeladmin_register function is replaced by modeladmin_register
  • {% load wagtailmodeladmin_tags %} has been replaced by {% load modeladmin_tags %}
  • search_fields now uses a list instead of a tuple


  • Fixed template overrides for django-admin templates


  • Added upload/download functionality for zipped media files


  • upgraded wagtial to 1.8
  • removed external dependency on wagtailmodeladmin to use internal wagtailadmin feature
  • added bulk-delete permission feature for the Moderator group
  • added edit permission for Main page to moderator and editor groups

Major revamp to the way we handle Multi Language on Molo and a bunch of new features

Main features:

- Revamped Multi Language support
- We added content automated content rotation and a way to schedule when content should be cycled
- We now offer specifying Google Analytics from the CMS for both GA and GTM (this uses celery for GA)
- Renamed HomePage module to BannerPage
- Changed content structure to introduce index pages
- Upgraded wagtail to 1.4.3
- We've added the option to allow un-translated pages to be hidden
- We now show a translated page on the front end when it's main language page is unpublished
- Add Topic of the Day functionality
- Add Support for both Elastichsearch 1.x & 2.x
- Add ability to show a highlighted term in the results
- Implement custom error page for CSRF error

Backwards incompatible changes

  • Deprecated use of LanguagePage: use SiteLanguage for multi-language support
  • Deprecated use of Main : all pages are now children of their index page (e.g. Section Pages are now children of Section Index Page)
  • Deprecated use of Section.featured_articles: use the template tag {% load_descendant_articles_for_section section featured_in_section=True %}
  • Deprecated use of Section.featured_articles_in_homepage: use the template tag {% load_descendant_articles_for_section section featured_in_homepage=True %}
  • Deprecated use of Section.latest_articles_in_homepage: use the template tag {% load_descendant_articles_for_section section featured_in_latest=True %}
  • Deprecated use of Section.articles: use the template tag {% load_child_articles_for_section page %}


  • Fix the bug with draft article publishing when content rotation is on


  • Ensure email address is set when using SSO


  • Put ForceDefaultLanguageMiddleware before django.middleware.locale.LocaleMiddleware


  • (bug) use datetime instead of UTC timezone for rotation


  • Add celery task for publishing pages


  • (bug) content rotation on homepage


  • (bug) only show published articles on front end


  • Add promote and demote dates to article promotion setting
  • Remove boolean promotion options
  • Data migration to set all articles with feature ticks to have a promotion start date
  • Order articles by promotion date


  • Enable the sharing of articles to Facebook and Twitter from the article page.


  • Change create to get_or_create in migration 47


  • Redefine core permissions for groups


  • Add clickable front-end tags to articles


  • Add migrations for external link


  • Signal on page moving and Allow adding external link to banner page


  • (bug) search URL was defined using the wrong regex (it broke Service Directory plugin)


  • Implement custom error page for CSRF error


  • Remove automatic opening of comments when an article is promoted to Topic of the Day


  • Exclude future-dated Topic of the Day articles from Latest articles list


  • Add Support for both Elastichsearch 1.x & 2.x
  • Add ability to show a highlighted term in the results

Note: Search highlighting is only supported by the Elasticsearch backend.


  • Add Topic of the Day functionality


  • Set GOOGLE_ANALYTICS to None in settings


  • Fix the issue with switching between child languages
  • Fix the issue with allowing articles to exist in multiple sections


  • Update user permissions


  • Ensure title is encoded properly for GA


  • Ensure title is filled in for GA middleware


  • Add custom GA celery middleware
  • Use celery for GA instead of gif pixel


  • Add middleware to ignore accept language header


  • Return the language code for languages that are not supported


  • Make sure Locales are not restricted to 2 char codes and we can use the country code


  • Return the language code for languages that babel is not supporting


  • Make sure unpublished translated pages are not appearing on front end


  • Show the translated page on front end when it’s main language page is unpublished


  • Add the option that untranslated pages will not be visible to the front end user when they viewing a child language of the site


  • Add date and time options to content rotation


  • Fixed Migration Bug


  • Add GA urls to Molo Urls
  • Pinned Flake8 to 2.6.2


  • Add local and global GA tracking codes


  • Add random content rotation for articles featured on homepage


  • Add global GA Tag model


  • Add get_translation template tag


  • Delete the translated page when a page is deleted


  • Return Marathon app & version information in the health checks.


  • Default count for sections set to 0


  • Add session key middleware for each user to use with GTM when javascript is disabled


  • Handling import * error with noqa


  • Delete translated page when a page is deleted
  • Added extra lang info for languages that django doesn’t support


  • Added wagtail multimedia support
  • Allow articles to exist in multiple sections


  • Fixed bugs with UC content importing, Arabic slugs and path issue


  • Fixed another small bug with UC content validation


  • Fixed a bug with UC content validation


  • Limit import content to users belonging to Universal Core Importers group


  • Content validation now happens in a celery task


  • Added pagination for articles in section
  • Show the active language and display the local name
  • Added load_sections template tag


  • Importing validation errors to be shown in the UI for celery task


  • Upgraded wagtail to 1.4.5
  • Effective style hint to support multi-language


  • Content import now happens in a celery task


  • Added templates for forgot password


  • Pined django-cas-ng to 3.5.4


  • Upgraded to Django 1.9 and Wagtail 1.4.4


  • Improved performance of UC content import


  • Changed molo.core version number in get_pypi_version test


  • Changed molo.core version number in versions_comparison test


  • Added multi-language support
  • Added content import from Universal Core content repos (using REACT)
  • Renamed HomePage module to BannerPage
  • Updated language switcher url to include ?next={{request.path}}
  • section_page.html now uses new template tags (see below)
  • section_listing_homepage.html now uses new template tags (see below)
  • Changed content structure to introduce index pages
  • Added GA tag manager field to site settings
  • Upgraded wagtail to 1.4.3

This is the initial release of Molo (1.x was considered beta)

Main features:

- Scafolding a Wagtail site with basic models
- Core features including Banners, Sections, Articles, Footer Pages, Search
- Out the box support for plugins (molo.profiles, molo.commenting, molo.yourwords, molo.polls)
- Upgraded Wagtail to 1.0


  • Moved tasks.py to core


  • Moved content rotation from cookiecutter to core


  • Added automatic content rotation


  • Added plugins version comparison
  • Added logo as wagtail setting


  • Re-release of version 2.6.12 because we forgot to increment the version number.


  • Added metadata tag field


  • Added social media fields


  • Ensure CAS only applies to admin views


  • Fixed the issue with CAS not being compatible with normal login


  • Updated plugins instructions
  • Updated the polls plugin in the documentation


  • core urls are not defined correctly


  • Bug fixes


  • Added search functionality
  • Updated core templates


  • Added support for Central Authentication Service (CAS)(CAS)


  • Updated documentation


  • Added missing files in the scaffold (pypi package) 2nd attempt


  • Added missing files in the scaffold (pypi package)


  • updated documentation
  • adding tags to ArticlePage model
  • upgraded wagtail to v1.3.1
  • better testing base for Molo


  • Promoted articles ‘featured in latest’ will be ordered by most recently updated in the latest section.


  • pinned cookiecutter to version 1.0.0


  • ordering of articles within a section uses the Wagtail ordering


  • bump to official wagtail v1.0
  • add health check


  • remove first_published_at from models (casuing migration issues)


  • added extra styling hints field to section page


  • allow articles to be featured on the homepage


  • first published at is not a required field


  • add homepage models
  • ensure articles ordered by published date
  • allow articles to be featured


  • Add images to sections
  • Add support for sub sections


  • Add multi language support


  • ensure libffi-dev in sideloader build file


  • ensure libffi-dev in sideloader build file


  • Add basic models
  • Add basic templates
  • upgraded to v1.0b2


  • Add sideloader scripts


  • Fix cookie cutter path


  • pypi fix - include cookie cutter json


  • Use cookie cutter for a project template


  • Fix pypi package manifest


  • Initial release