In-line Editing

Mezzanine comes with the ability for content authors to edit content directly within a page while viewing it on the website, rather than having to log into the admin area. Content authors can simply log into the admin area as usual, but by selecting Site on the login screen the author will then be redirected back to the website where a small Edit icon will be found next to each piece of editable content, such as a page’s title or a blog post’s body. Clicking on the Edit icon will allow the author to update the individual piece of content without leaving the page.

In-line editing can be disabled by setting INLINE_EDITING_ENABLED to False.

Template Configuration

Making content in-line editable is as simple as wrapping model fields with a template tag in your templates. The default templates installed with Mezzanine all have their content configured to be in-line editable. When developing your own templates from scratch though, you’ll need to perform this step yourself.

The first step is to ensure the editable_loader() template tag is called right before the closing </body> tag in each template. The recommended way to do this is to include includes/footer_scripts in your top-most base template:

{% load mezzanine_tags %}
<html>
<head>
    <title>My Website</title>
</head>
<body>
    <!-- Content goes here -->
    {% include "includes/footer_scripts.html" %}
</body>
</html>

If your site does not use jQuery, you’ll need to include it conditionally in your template’s <head> if the user is a staff member. If you’re using a different JS library, you can use jQuery.noConflict() to avoid it overwriting the $ symbol.

{% if user.is_staff %}
    <script src="{{ STATIC_URL }}mezzanine/js/jquery-1.8.3.min.js">
        jQuery.noConflict();
    </script>
{% endif %}

The second step is to wrap each instance of a model field with the editable() and endeditable template tags, with the field specified as the editable() tag’s argument. The content between the two tags is what will visibly be hinted to the content author as being editable. It’s possible to not provide any content between the two tags, in which case the value for the model field specified for the editable() tag will simply be used. The model field must always be specified in the format instance_name.field_name where instance_name is the name of a model instance in the template context. For example, suppose we had a page variable in our template with title and content fields:

{% load mezzanine_tags %}
<html>
<head>
    <title>{{ page.title }}</title>
</head>
<body>

    <!--
    No content is specified between the editable tags here, so the
    page.title field is simply displayed inside the <h1> tags.
    -->
    <h1>
        {% editable page.title %}{% endeditable %}
    </h1>

    <!--
    Here we are manipulating how the editable content will be regularly
    displayed on the page using Django's truncatewords_html filter as
    well as some in-line markup.
    -->
    <div>
        {% editable page.content %}
        <p style="text-align:justify;">
            {{ page.content|truncatewords_html:50 }}
        </p>
        {% endeditable %}
    </div>

    {% editable_loader %}
</body>
</html>

The editable() template tag also allows multiple fields for a model instance to be given as arguments to a single editable() tag. The result of this is still a single Edit icon, but when clicked will display each of the fields specified for editing, grouped together in a single form. Continuing on from the previous example, if we wanted to group together the title and content fields:

{% load mezzanine_tags %}
<html>
<head>
    <title>{{ page.title }}</title>
</head>
<body>

    <!--
    A single Edit icon will be displayed indicating the entire area
    around the h1 and div tags is editable. Clicking it reveals a form
    for editing both fields at once.
    -->
    {% editable page.title page.content %}
    <h1>
        {{ page.title }}
    </h1>
    <div>
        <p style="text-align:justify;">
            {{ page.content|truncatewords_html:50 }}
        </p>
    </div>
    {% endeditable %}

    {% editable_loader %}
</body>
</html>

The only caveat to consider with grouping together fields in a single editable() tag is that they must all belong to the same model instance.