Package: django-compose-tags
Django Compose TagCompose templates easilyDjango Compose tags provide the tags to ease templates composition,
with an api close to theincludetemplate tag.The api is thought to ease the implementation and usage of design systems in django.OverviewWrite your template as you would for theincludetag:<!-- card.html --><article class="card"><div class="card-body">{{children}}</div><footer class="card-footer">{{footer}}</footer></article>ThecomposetagThecomposetemplate tag behave similarly todjango'sinclude.
The main difference is that the content between{% compose %}and{% endcompose %}is regular django template that's accessible withing the composed template as the{{ children }}variable.{%loadcompose%}{%compose"card.html"footer="My footer"%}<p>card.html receive this as the{{children}}variable</p><p>You can use{{context_varialbe}}in here.</p>{%endcompose%}By default the composed template doesn't have access to the context, if you need access to the context set the takes_context option{% compose "card.html" takes_context %}.takes_contextis the opposite of theonlyThedefinetagdefineThedefinetemplate tag allows you to set a new variable from within a template. That's a convenient way to use template rendered variables for any tag parameter.{%definemylink%}<a href={{link.url}}>Go to{{link.name}}{%enddefine%}{%include"card.html"children="Card body"footer=mylink%}{%compose"card.html"footer=mylink%}Card body with{{context_variable}}{%endcompose%}Custom composition tagcomposition_tagis tocomposewhatinclustion_tagis to theincludetag.Define you tag function and decorate it withcomposition_tag, the decorator takes care of passing the children as the first argument of your custom tag.# mydesignsystem/templatetags/mydesignsystem.pyfromdjango.templateimportLibraryfromcompose_tagsimportcomposition_tagregister=Library()@register.tag@composition_tag('card.html',takes_context=True)defcard(children,context,next,cancelable=False):return{"children":children,"footer":create_footer(next,cancelable),}Then use it in your templates, by default the tag is named after your function name.{%loadmydesignsystem%}{%cardnext=someurlcancelable=True%}My card children{%endcard%}Declaring composition_tagThere are multiple ways to use composition_tag. The first is as a decorator:@register.tag@composition_tag('template.html')defmytag(children,**kwargs):# Usage: {% mytag %}children{% endmytag %}...@register.tag("customname")@composition_tag('template.html')defmytag(children,**kwargs):# Usage: {% customname %}children{% endcustomname %}...When you don't need to do any python processing, there is a default implementation that forward all parameters as is.
When you rely on that default implementation the default tag name is derived from the template name.Which meanregister.tag(composition_tag("button.html"))is equivalent to@register.tag@composition_tag('button.html')defbutton(children,**kwargs):return{**kwargs,"children":children}As with the decorator usage, you can override the tag name:register.tag("mybutton", composition_tag("button.html"))RequirementsPython (3.6, 3.7, 3.8, 3.9, 3.10, 3.11)Django (2.2, 3.0, 3.1, 3.2, 4.0, 4.1)Wehighly recommendand only officially support the latest patch release of
each Python and Django series.InstallationInstall usingpip install django-compose-tagsAdd'compose_tags'to yourINSTALLED_APPSsetting.INSTALLED_APPS=[...'compose_tags',]If you usecomposea lot we recommend you add it to your builtins:TEMPLATES=[{"BACKEND":"django.template.backends.django.DjangoTemplates","OPTIONS":{# ..."builtins":["compose_tags.templatetags.compose"],}}]AlternativesDjango Compose Tag purposely provide a simple api based solely on templates.If Django Compose Tag doesn't cover your requirements we recommend you take a look atjinja.