:sequential_nav: both .. _tutorial_templates: Templates and placeholders ========================== So far the CMS rendered your pages using the project's default ``base.html``, which simply extends a template from djangocms-frontend and exposes a single ``Page Content`` placeholder. In this chapter you will replace that base template with your own, defining two placeholders — ``Header`` and ``Body`` — so editors can manage a header strip *and* a body separately. Goal ---- At the end of this chapter, the homepage uses a template you wrote and exposes two placeholders: ``Header`` and ``Body``. Editors can place plugins into either one. 1. Find the project's base template ----------------------------------- The ``djangocms`` command already created a base template for you and told both Django and the CMS about it: - The template lives at ``coffeesite/templates/base.html``. - ``settings.py`` already points ``TEMPLATES`` → ``DIRS`` at ``coffeesite/templates``, so Django finds it. You do **not** need to create a new directory or edit ``DIRS``. - ``settings.py`` already registers it for the CMS: .. code-block:: python CMS_TEMPLATES = [ ("base.html", "Standard"), ] The second entry of each tuple is the human-readable label shown in the toolbar. Rename ``"Standard"`` to something like ``"Coffee Roaster — base"`` if you like; there is no need to add a new entry. Open ``coffeesite/templates/base.html``. Out of the box it is a two-line stub that extends a template from djangocms-frontend — that is where the single ``Page Content`` placeholder from the previous chapter comes from: .. code-block:: html+django {# Replace this with your base template #} {% extends "bootstrap5/base.html" %} We will replace this stub with our own markup. 2. Write your own base template ------------------------------- Replace the contents of ``coffeesite/templates/base.html`` with: .. code-block:: html+django {% load cms_tags sekizai_tags %} {% page_attribute "page_title" %} – Coffee Roaster {% render_block "css" %} {% cms_toolbar %}
{% placeholder "Header" %}
{% placeholder "Body" %}
{% render_block "js" %} A few things to notice: - ``{% placeholder "Name" %}`` is what creates a placeholder. The name is what editors see in the toolbar. - ``{% cms_toolbar %}`` is required for the toolbar to render — without it, you cannot edit. - ``{% render_block "css" %}`` and ``{% render_block "js" %}`` come from `django-sekizai `_. Plugins ship their own CSS and JavaScript; when several plugins on the same page need the same asset, sekizai collects them so each block is rendered exactly once, in the right place in the document. Every django CMS template needs the ``"css"`` block in ```` and the ``"js"`` block just before ````. For everything ``{% placeholder %}`` accepts, see :doc:`/reference/placeholders`. For the conceptual story, see :doc:`/explanation/plugins`. 3. Reload the page ------------------ The home page already uses ``base.html``, so there is no template to switch — your new markup takes effect as soon as the file is saved. #. Reload the *Home* page in your browser in edit mode. #. You will see two empty placeholders labelled ``Header`` and ``Body``. If the new placeholders do not appear, restart ``runserver`` and reload the page. .. note:: The text you added to ``Page Content`` in the previous chapter is still stored, but it no longer appears: the new template does not include a ``Page Content`` placeholder, so its plugins are not rendered. .. image:: images/empty-placeholders.png :class: screenshot :alt: the page in edit mode immediately after editing the template — the structure board shows two empty placeholders labelled Header and Body :align: center :width: 600 4. Fill the placeholders ------------------------ #. Drop a **Text** plugin into ``Header`` and type the site name — "Coffee Roaster". #. Drop a **Text** plugin into ``Body`` and write a short welcome paragraph. #. **Publish** the page. Visit the homepage in a private window. You should see a header strip above the body content. .. image:: images/header-and-body.png :class: screenshot :alt: the homepage with the site-name header strip on top and the welcome paragraph below :align: center :width: 600 What just happened ------------------ You now own the markup. Two new ideas appeared: - A **template** declares which placeholders exist on a page. Different templates can declare different placeholders. - **CMS_TEMPLATES** is the list of templates editors can pick from. Anything you would do in a normal Django template — ``{% block %}`` inheritance, ``{% include %}``, ``{% url %}`` — works inside a CMS template. The only CMS-specific tags you need for now are ``{% cms_toolbar %}`` and ``{% placeholder %}``. A reusable region with ``static_alias`` --------------------------------------- If you want a region whose content is *the same on every page* (a footer, for example), use ``{% static_alias %}`` instead of ``{% placeholder %}``. It works similarly for editors, but the content is stored once and reused everywhere: .. code-block:: html+django Add that to ``base.html`` if you like. Do not forget to add ``{% load djangocms_alias_tags %}`` at the top of the file to let Django know about the static alias tag. The full mechanics live in :doc:`/how_to/04-templates`. Going further ------------- - :doc:`/how_to/04-templates` — multiple templates, inheritance, per-page template overrides. - :doc:`/how_to/01-placeholders` — placeholders outside CMS pages (e.g. on your own Django models). In the next chapter we leave the toolbar and write our first custom plugin in Python.