Your first Wagtail site

Note

This tutorial covers setting up a brand new Wagtail project. If you’d like to add Wagtail to an existing Django project instead, see Integrating Wagtail into a Django project.

  1. Install Wagtail and its dependencies:

    pip install wagtail
    
  2. Start your site:

    wagtail start mysite
    cd mysite
    

    Wagtail provides a start command similar to django-admin.py startproject. Running wagtail start mysite in your project will generate a new mysite folder with a few Wagtail-specific extras, including the required project settings, a “home” app with a blank HomePage model and basic templates and a sample “search” app.

  3. Install project dependencies:

    pip install -r requirements.txt
    

    This ensures that you have the relevant version of Django for the project you’ve just created.

  4. Create the database:

    python manage.py migrate
    

    If you haven’t updated the project settings, this will be a SQLite database file in the project directory.

  5. Create an admin user:

    python manage.py createsuperuser
    
  6. python manage.py runserver If everything worked, http://127.0.0.1:8000 will show you a welcome page

    Wagtail welcome message

    You can now access the administrative area at http://127.0.0.1:8000/admin

    Administrative screen

Extend the HomePage model

Out of the box, the “home” app defines a blank HomePage model in models.py, along with a migration that creates a homepage and configures Wagtail to use it.

Edit home/models.py as follows, to add a body field to the model:

from __future__ import unicode_literals

from django.db import models

from wagtail.wagtailcore.models import Page
from wagtail.wagtailcore.fields import RichTextField
from wagtail.wagtailadmin.edit_handlers import FieldPanel


class HomePage(Page):
    body = RichTextField(blank=True)

    content_panels = Page.content_panels + [
        FieldPanel('body', classname="full")
    ]

body is defined as RichTextField, a special Wagtail field. You can use any of the Django core fields. content_panels define the capabilities and the layout of the editing interface. More on creating Page models.

Run python manage.py makemigrations, then python manage.py migrate to update the database with your model changes. You must run the above commands each time you make changes to the model definition.

You can now edit the homepage within the Wagtail admin area (go to Explorer, Homepage, then Edit) to see the new body field. Enter some text into the body field, and publish the page.

The page template now needs to be updated to reflect the changes made to the model. Wagtail uses normal Django templates to render each page type. It automatically generates a template filename from the model name by separating capital letters with underscores (e.g. HomePage becomes home_page.html). Edit home/templates/home/home_page.html to contain the following:

{% extends "base.html" %}

{% load wagtailcore_tags %}

{% block body_class %}template-homepage{% endblock %}

{% block content %}
    {{ page.body|richtext }}
{% endblock %}
Updated homepage

Wagtail template tags

Wagtail provides a number of template tags & filters which can be loaded by including {% load wagtailcore_tags %} at the top of your template file.

In this tutorial, we use the richtext filter to escape and print the contents of a RichTextField:

{% load wagtailcore_tags %}
{{ page.body|richtext }}

Produces:

<div class="rich-text">
    <p>
        <b>Welcome</b> to our new site!
    </p>
</div>

Note: You’ll need to include {% load wagtailcore_tags %} in each template that uses Wagtail’s tags. Django will throw a TemplateSyntaxError if the tags aren’t loaded.

A basic blog

We are now ready to create a blog. To do so, run python manage.py startapp blog to create a new app in your Wagtail site.

Add the new blog app to INSTALLED_APPS in mysite/settings/base.py.

The following example defines a basic blog post model in blog/models.py:

from django.db import models

from wagtail.wagtailcore.models import Page
from wagtail.wagtailcore.fields import RichTextField
from wagtail.wagtailadmin.edit_handlers import FieldPanel
from wagtail.wagtailsearch import index


class BlogPage(Page):
    date = models.DateField("Post date")
    intro = models.CharField(max_length=250)
    body = RichTextField(blank=True)

    search_fields = Page.search_fields + [
        index.SearchField('intro'),
        index.SearchField('body'),
    ]

    content_panels = Page.content_panels + [
        FieldPanel('date'),
        FieldPanel('intro'),
        FieldPanel('body', classname="full")
    ]

Note

On Wagtail versions before 1.5, search_fields needs to be defined as a tuple:

search_fields = Page.search_fields + (
    index.SearchField('intro'),
    index.SearchField('body'),
)

Create a template at blog/templates/blog/blog_page.html:

{% extends "base.html" %}

{% load wagtailcore_tags %}

{% block body_class %}template-blogpage{% endblock %}

{% block content %}
    <h1>{{ page.title }}</h1>
    <p class="meta">{{ page.date }}</p>

    <div class="intro">{{ page.intro }}</div>

    {{ page.body|richtext }}
{% endblock %}

Run python manage.py makemigrations and python manage.py migrate.

Create page screen
Page edit screen

Image support

Wagtail provides support for images out of the box. To add them to your model:

from django.db import models

from wagtail.wagtailcore.models import Page
from wagtail.wagtailcore.fields import RichTextField
from wagtail.wagtailadmin.edit_handlers import FieldPanel
from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
from wagtail.wagtailsearch import index


class BlogPage(Page):
    main_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    date = models.DateField("Post date")
    intro = models.CharField(max_length=250)
    body = RichTextField(blank=True)

    search_fields = Page.search_fields + [
        index.SearchField('intro'),
        index.SearchField('body'),
    ]

    content_panels = Page.content_panels + [
        FieldPanel('date'),
        ImageChooserPanel('main_image'),
        FieldPanel('intro'),
        FieldPanel('body'),
    ]

Run python manage.py makemigrations and python manage.py migrate.

Adjust your blog page template to include the image:

{% extends "base.html" %}

{% load wagtailcore_tags wagtailimages_tags %}

{% block body_class %}template-blogpage{% endblock %}

{% block content %}
    <h1>{{ page.title }}</h1>
    <p class="meta">{{ page.date }}</p>

    {% if page.main_image %}
        {% image page.main_image width-400 %}
    {% endif %}

    <div class="intro">{{ page.intro }}</div>

    {{ page.body|richtext }}
{% endblock %}
A blog post sample

You can read more about using images in templates in the docs.

Blog Index

Let us extend the Blog app to provide an index.

class BlogIndexPage(Page):
    intro = RichTextField(blank=True)

    content_panels = Page.content_panels + [
        FieldPanel('intro', classname="full")
    ]

The above creates an index type to collect all our blog posts.

blog/templates/blog/blog_index_page.html

{% extends "base.html" %}

{% load wagtailcore_tags %}

{% block body_class %}template-blogindexpage{% endblock %}

{% block content %}
    <h1>{{ page.title }}</h1>

    <div class="intro">{{ page.intro|richtext }}</div>
{% endblock %}

Where next