(writing_templates)= # Writing templates Wagtail uses Django's templating language. For developers new to Django, start with Django's own template documentation: [](inv:django#topics/templates) Python programmers new to Django/Wagtail may prefer more technical documentation: [](inv:django#ref/templates/api) You should be familiar with Django templating basics before continuing with this documentation. ## Templates Every type of page or "content-type" in Wagtail is defined as a "model" in a file called `models.py`. If your site has a blog, you might have a `BlogPage` model and another called `BlogPageListing`. The names of the models are up to the Django developer. For each page model in `models.py`, Wagtail assumes an HTML template file exists of (almost) the same name. The Front End developer may need to create these templates themselves by referring to `models.py` to infer template names from the models defined therein. To find a suitable template, Wagtail converts CamelCase names to snake_case. So for a `BlogPage` model, a template `blog_page.html` will be expected. The name of the template file can be overridden per model if necessary. Template files are assumed to exist here: ``` name_of_project/ name_of_app/ templates/ name_of_app/ blog_page.html models.py ``` For more information, see the Django documentation for the [application directories template loader](inv:django#ref/templates/api). ### Page content The data/content entered into each page is accessed/output through Django's `{{ double-brace }}` notation. Each field from the model must be accessed by prefixing `page.`. For example the page title `{{ page.title }}` or an author field `{{ page.author }}`. A custom variable name can be configured on the page model {attr}`wagtail.models.Page.context_object_name`. If a custom name is defined, `page` is still available for use in shared templates. Additionally, `request.` is available and contains Django's request object. ## Static assets Static files (such as CSS, JS, and images) are typically stored here: ``` name_of_project/ name_of_app/ static/ name_of_app/ css/ js/ images/ models.py ``` (The names "css", "js" etc aren't important, only their position within the tree.) Any file within the static folder should be inserted into your HTML using the `{% static %}` tag. More about it: [](static_tag). ### User images Images uploaded to a Wagtail site by its users (as opposed to a developer's static files, mentioned above) go into the image library and from there are added to pages via the page editor interface. Unlike other CMSs, adding images to a page does not involve choosing a "version" of the image to use. Wagtail has no predefined image "formats" or "sizes". Instead, the template developer defines image manipulation to occur _on the fly_ when the image is requested, via a special syntax within the template. Images from the library must be requested using this syntax, but a developer's static images can be added via conventional means like `img` tags. Only images from the library can be manipulated on the fly. Read more about the image manipulation syntax here: [](image_tag). (template_tags_and_filters)= ## Template tags & filters In addition to Django's standard tags and filters, Wagtail provides some of its own, which can be `load`-ed [just like any other](inv:django#howto/custom-template-tags). ## Images (tag) The `image` tag inserts an XHTML-compatible `img` element into the page, setting its `src`, `width`, `height`, and `alt`. See also [](image_tag_alt). The syntax for the `image` tag is thus: ```html+django {% image [image] [resize-rule] %} ``` For example: ```html+django {% load wagtailimages_tags %} ... {% image page.photo width-400 %} {% image page.photo fill-80x80 %} ``` See [](image_tag) for full documentation. ### Images in multiple formats The `picture` tag works like `image`, but allows specifying multiple formats to generate a `` element with `` elements and a fallback ``. For example: ```html+django {% load wagtailimages_tags %} ... {% picture page.photo format-{avif,webp,jpeg} width-400 %} ``` See [](multiple_formats) for full documentation. ### Images in multiple sizes The `srcset_image` tag works like `image`, but allows specifying multiple sizes to generate a `srcset` attribute and leverage [responsive image rules](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images). For example: ```html+django {% load wagtailimages_tags %} ... {% srcset_image page.photo width-{400,800} sizes="(max-width: 600px) 400px, 80vw" %} ``` This can also be done with `picture`, to generate multiple formats and sizes at once: ```html+django {% picture page.photo format-{avif,webp,jpeg} width-{400,800} sizes="80vw" %} ``` See [](responsive_images) for full documentation. (rich_text_filter)= ## Rich text (filter) The `richtext` filter takes a chunk of HTML content and renders it as safe HTML on the page. Importantly, it also expands internal shorthand references to embedded images and links made in the Wagtail editor, into fully-baked HTML ready for display. Only fields using `RichTextField` need this applied in the template. ```html+django {% load wagtailcore_tags %} ... {{ page.body|richtext }} ``` (responsive_embeds)= ### Responsive Embeds As Wagtail does not impose any styling of its own on templates, images, and embedded media will be displayed at a fixed width as determined by the HTML. Images can be made to resize to fit their container using a CSS rule such as the following: ```css .body img { max-width: 100%; height: auto; } ``` where `body` is a container element in your template surrounding the images. Making embedded media resizable is also possible, but typically requires custom style rules matching the media's aspect ratio. To assist in this, Wagtail provides built-in support for responsive embeds, which can be enabled by setting `WAGTAILEMBEDS_RESPONSIVE_HTML = True` in your project settings. This adds a CSS class of `responsive-object` and an inline `padding-bottom` style to the embed: ```{literalinclude} ../../wagtail/embeds/templates/wagtailembeds/embed_frontend.html :language: html+django ``` The built-in template (`wagtailembeds/embed_frontend.html`) above is to be used in conjunction with the following CSS: ```css .responsive-object { position: relative; } .responsive-object iframe, .responsive-object object, .responsive-object embed { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } ``` For sites enforcing a Content Security Policy, you can override the `wagtailembeds/embed_frontend.html` template to apply the inline styles via a `