From 5e06b970956af4854e970e74990cb971ba31c96b Mon Sep 17 00:00:00 2001 From: farhan Date: Tue, 3 Jun 2025 10:32:34 +0500 Subject: Fixed #36410 -- Added support for Template Partials to the Django Template Language. Introduced `{% partialdef %}` and `{% partial %}` template tags to define and render reusable named fragments within a template file. Partials can also be accessed using the `template_name#partial_name` syntax via `get_template()`, `render()`, `{% include %}`, and other template-loading tools. Adjusted `get_template()` behavior to support partial resolution, with appropriate error handling for invalid names and edge cases. Introduced `PartialTemplate` to encapsulate partial rendering behavior. Includes tests and internal refactors to support partial context binding, exception reporting, and tag validation. Co-authored-by: Carlton Gibson Co-authored-by: Natalia <124304+nessita@users.noreply.github.com> Co-authored-by: Nick Pope --- docs/ref/templates/builtins.txt | 74 +++++++++++++++++++++ docs/ref/templates/language.txt | 144 ++++++++++++++++++++++++++++++++++++++++ docs/releases/6.0.txt | 15 +++++ docs/topics/templates.txt | 27 ++++++++ 4 files changed, 260 insertions(+) (limited to 'docs') diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt index 1eb391d8c0..464c4d83ac 100644 --- a/docs/ref/templates/builtins.txt +++ b/docs/ref/templates/builtins.txt @@ -957,6 +957,80 @@ output (as a string) inside a variable. This is useful if you want to use {% now "Y" as current_year %} {% blocktranslate %}Copyright {{ current_year }}{% endblocktranslate %} +.. templatetag:: partial + +``partial`` +----------- + +.. versionadded:: 6.0 + +Renders a template fragment that was defined with :ttag:`partialdef`, inserting +the matching partial at this location. + +Usage: + +.. code-block:: html+django + + {% partial partial_name %} + +The ``partial_name`` argument is the name of the template fragment to render. + +In the following example, a partial named ``button`` is defined and then +rendered three times: + +.. code-block:: html+django + + {% partialdef button %} + + {% endpartialdef %} + + {% partial button %} + {% partial button %} + {% partial button %} + +.. templatetag:: partialdef + +``partialdef`` +-------------- + +.. versionadded:: 6.0 + +Defines a reusable template fragment that can be rendered multiple times within +the same template or accessed directly via :ref:`template loading or inclusion +`. + +Usage: + +.. code-block:: html+django + + {% partialdef partial_name %} + {# Reusable content. #} + {% endpartialdef %} + +The ``partial_name`` argument is required and must be a valid template +identifier. + +In the following example, a new fragment named ``card`` is defined: + +.. code-block:: html+django + + {% partialdef card %} +
+

{{ title }}

+

{{ content }}

+
+ {% endpartialdef %} + +This partial can then be rendered using the :ttag:`partial` tag: + +.. code-block:: html+django + + {% partial card %} + {% partial card %} + +To :ref:`render a fragment immediately in place `, +use the ``inline`` option. The partial is still stored and can be reused later. + .. templatetag:: querystring ``querystring`` diff --git a/docs/ref/templates/language.txt b/docs/ref/templates/language.txt index 16a3682086..e8812666fa 100644 --- a/docs/ref/templates/language.txt +++ b/docs/ref/templates/language.txt @@ -475,6 +475,150 @@ it also defines the content that fills the hole in the *parent*. If there were two similarly-named :ttag:`block` tags in a template, that template's parent wouldn't know which one of the blocks' content to use. +.. _template-partials: + +Template partials +================= + +.. versionadded:: 6.0 + +Template partials define reusable template fragments within a template file. +They are self-contained components that can be rendered multiple times within +the same template, helping to avoid repetition and maintain consistent output. + +Basic syntax +------------ + +A partial can be defined using the :ttag:`partialdef` tag: + +.. code-block:: html+django + :caption: ``authors.html`` + + {% partialdef user-info %} +
+

{{ user.name }}

+

{{ user.bio }}

+
+ {% endpartialdef %} + +For extra readability, the name can be included in the ``{% endpartialdef %}`` +closing tag: + +.. code-block:: html+django + + {% partialdef user-info %} + {# ... #} + {% endpartialdef user-info %} + +The template fragment can be rendered using the :ttag:`partial` tag: + +.. code-block:: html+django + + {% partial user-info %} + +Fragment reuse +-------------- + +A template fragment can be reused multiple times: + +.. code-block:: html+django + :caption: ``authors.html`` + + {% block content %} +

Authors

+ {% for user in authors %} + {% partial user-info %} + {% endfor %} + +

Editors

+ {% for user in editors %} + {% partial user-info %} + {% endfor %} + {% endblock %} + +The partial content is rendered each time the named partial is used, with the +current template context. + +.. _template-partials-inline: + +Inline partials +--------------- + +A template fragment can be defined and rendered in-place using the ``inline`` +argument. This defines the partial for later reuse while also rendering it +immediately at its definition: + +.. code-block:: html+django + + {# Define and render immediately. #} + {% partialdef user-info inline %} +
+

{{ user.name }}

+

{{ user.bio }}

+
+ {% endpartialdef %} + + {# Other page content here. #} + + {# Reuse later elsewhere in the template. #} + + +.. _template-partials-direct-access: + +Accessing partials directly +--------------------------- + +Template fragments defined with :ttag:`partialdef` can be accessed directly via +template loading or inclusion using the ``template.html#partial_name`` syntax. + +For example, using the :func:`~django.shortcuts.render` shortcut, the following +code renders only the partial named ``user-info`` defined in the +``authors.html`` template:: + + from django.contrib.auth.models import User + from django.shortcuts import get_object_or_404, render + + + def user_info_partial(request, user_id): + user = get_object_or_404(User, id=user_id) + return render(request, "authors.html#user-info", {"user": user}) + +This approach is particularly useful for AJAX-style requests that update only +specific portions of a page with the rendered template fragment. + +Template partials can also be included using the :ttag:`include` template tag +with the same ``#`` directive: + +.. code-block:: html+django + + {% include "authors.html#user-info" %} + +Context handling +---------------- + +Template partials are rendered with the current template context. They work as +expected in loops and with context variables: + +.. code-block:: html+django + + {% for user in users %} + {% partial user-info %} + {% endfor %} + +Context variables can be adjusted using the :ttag:`with` tag: + +.. code-block:: html+django + + {% with user=featured_author %} +

Featured Author of the Month

+ {% partial user-info %} + {% endwith %} + .. _next section: #automatic-html-escaping .. _automatic-html-escaping: diff --git a/docs/releases/6.0.txt b/docs/releases/6.0.txt index 0c1a2c87eb..3e250706ec 100644 --- a/docs/releases/6.0.txt +++ b/docs/releases/6.0.txt @@ -91,6 +91,21 @@ Notably, the return type of the :class:`EmailMessage.message() previous ``SafeMIMEText`` and ``SafeMIMEMultipart`` return types, but is not an instance of those now-deprecated classes. +Template Partials +----------------- + +The :ref:`Django Template Language ` now supports +:ref:`template partials ` , making it easier to encapsulate +and reuse small named fragments within a template file. The new tags +:ttag:`{% partialdef %} ` and :ttag:`{% partial %} ` +define a partial and render it, respectively. + +Partials can also be referenced using the ``template_name#partial_name`` syntax +with :func:`~django.template.Engine.get_template`, +:func:`~django.shortcuts.render`, :ttag:`{% include %}`, and other +template-loading tools, enabling more modular and maintainable templates +without needing to split components into separate files. + Minor features -------------- diff --git a/docs/topics/templates.txt b/docs/topics/templates.txt index df55cccb06..1b5559db5a 100644 --- a/docs/topics/templates.txt +++ b/docs/topics/templates.txt @@ -306,6 +306,33 @@ The ``django.template.loader`` module defines two functions to load templates. If you want to restrict the search to a particular template engine, pass the engine's :setting:`NAME ` in the ``using`` argument. + **Partial loading:** + + When using the :class:`~django.template.backends.django.DjangoTemplates` + backend, a specific fragment from a template can be loaded by name. This + fragment should have been previously defined using the :ttag:`partialdef` + template tag:: + + from django.template.loader import get_template + + # Load an entire template. + template = get_template("template.html") + + # Load a specific fragment from a template. + partial = get_template("template.html#partial_name") + + When loading a partial, the returned object behaves like a regular + ``Template`` but contains only the partial's content. + + See :ref:`template-partials` for more information about defining and using + template fragments. + + .. versionchanged:: 6.0 + + Support for loading template partials when using the + :class:`~django.template.backends.django.DjangoTemplates` backend was + added. + .. function:: select_template(template_name_list, using=None) ``select_template()`` is just like ``get_template()``, except it takes a -- cgit v1.3