{"id":75728,"date":"2020-01-20T11:53:43","date_gmt":"2020-01-20T06:23:43","guid":{"rendered":"https:\/\/www.vskills.in\/certification\/tutorial\/?p=75728"},"modified":"2024-04-12T14:17:15","modified_gmt":"2024-04-12T08:47:15","slug":"extending-the-template-system","status":"publish","type":"page","link":"https:\/\/www.vskills.in\/certification\/tutorial\/extending-the-template-system\/","title":{"rendered":"Extending the Template System"},"content":{"rendered":"<p>Now that you understand a bit more about the internals of the template system, let\u2019s look at how to extend the system with custom code. Most template customization comes in the form of custom template tags and\/or filters. Although the Django template language comes with many built-in tags and filters, you\u2019ll probably assemble your own libraries of tags and filters that fit your own needs. Fortunately, it\u2019s quite easy to define your own functionality.<\/p>\n<p><strong>Creating a Template Library<\/strong> &#8211; Whether you\u2019re writing custom tags or filters, the first thing to do is to create a <strong>template library<\/strong> \u2014 a small bit of infrastructure Django can hook into. Creating a template library is a two-step process:<\/p>\n<ul>\n<li>First, decide which Django application should house the template library. If you\u2019ve created an app via py startapp, you can put it in there, or you can create another app solely for the template library. Whichever route you take, make sure to add the app to your INSTALLED_APPS setting. We\u2019ll explain this shortly.<\/li>\n<li>Second, create a templatetags directory in the appropriate Django application\u2019s package. It should be on the same level as py, views.py, and so forth. For example:<\/li>\n<\/ul>\n<p>books\/&nbsp;&nbsp; __init__.py&nbsp;&nbsp; models.py&nbsp;&nbsp; templatetags\/&nbsp;&nbsp; views.py<\/p>\n<p>Create two empty files in the templatetags directory: an __init__.py file (to indicate to Python that this is a package containing Python code) and a file that will contain your custom tag\/filter definitions. The name of the latter file is what you\u2019ll use to load the tags later. For example, if your custom tags\/filters are in a file called poll_extras.py, you\u2019d write the following in a template:<\/p>\n<p>{% load poll_extras %}<\/p>\n<p>The {% load %} tag looks at your INSTALLED_APPS setting and only allows the loading of template libraries within installed Django applications. This is a security feature; it allows you to host Python code for many template libraries on a single computer without enabling access to all of them for every Django installation.<\/p>\n<p>If you write a template library that isn\u2019t tied to any particular models\/views, it\u2019s valid and quite normal to have a Django application package that contains only a templatetags package. There\u2019s no limit on how many modules you put in the templatetags package. Just keep in mind that a {% load %} statement will load tags\/filters for the given Python module name, not the name of the application. Once you\u2019ve created that Python module, you\u2019ll just have to write a bit of Python code, depending on whether you\u2019re writing filters or tags.<\/p>\n<p>To be a valid tag library, the module must contain a module-level variable named register that is a template.Library instance. This template.Library instance is the data structure in which all the tags and filters are registered. So, near the top of your module, insert the following:<\/p>\n<p>from django import template<\/p>\n<p>register = template.Library()<\/p>\n<p><strong>Note<\/strong> &#8211; For a good number of examples, read the source code for Django\u2019s default filters and tags. They\u2019re in django\/template\/defaultfilters.py and django\/template\/defaulttags.py, respectively. Some applications in django.contrib also contain template libraries. Once you\u2019ve created this register variable, you\u2019ll use it to create template filters and tags.<\/p>\n<p><strong>Writing Custom Template Filters<\/strong> &#8211; Custom filters are just Python functions that take one or two arguments:<\/p>\n<ul>\n<li>The value of the variable (input)<\/li>\n<li>The value of the argument, which can have a default value or be left out altogether<\/li>\n<\/ul>\n<p>For example, in the filter {{ var|foo:&#8221;bar&#8221; }}, the filter foo would be passed the contents of the variable var and the argument &#8220;bar&#8221;. Filter functions should always return something. They shouldn\u2019t raise exceptions, and they should fail silently. If there\u2019s an error, they should return either the original input or an empty string, whichever makes more sense. Here\u2019s an example filter definition:<\/p>\n<p>def cut(value, arg):&nbsp;&nbsp; &#8220;Removes all values of arg from the given string&#8221;&nbsp;&nbsp; return value.replace(arg, &#8221;)<\/p>\n<p>And here\u2019s an example of how that filter would be used:<\/p>\n<p>{{ somevariable|cut:&#8221;0&#8243; }}<\/p>\n<p>Most filters don\u2019t take arguments. In this case, just leave the argument out of your function:<\/p>\n<p>def lower(value): # Only one argument.&nbsp;&nbsp; &#8220;Converts a string into all lowercase&#8221;&nbsp;&nbsp; return value.lower()<\/p>\n<p>When you\u2019ve written your filter definition, you need to register it with your Library instance, to make it available to Django\u2019s template language:<\/p>\n<p>register.filter(&#8216;cut&#8217;, cut)register.filter(&#8216;lower&#8217;, lower)<\/p>\n<p>The Library.filter() method takes two arguments:<\/p>\n<ul>\n<li>The name of the filter (a string)<\/li>\n<li>The filter function itself<\/li>\n<\/ul>\n<p>If you\u2019re using Python 2.4 or above, you can use register.filter() as a decorator instead:<\/p>\n<p>@register.filter(name=&#8217;cut&#8217;)def cut(value, arg):&nbsp;&nbsp; return value.replace(arg, &#8221;)&nbsp;@register.filterdef lower(value):&nbsp;&nbsp; return value.lower()<\/p>\n<p>If you leave off the name argument, as in the second example, Django will use the function\u2019s name as the filter name. Here, then, is a complete template library example, supplying the cut filter:<\/p>\n<p>from django import template&nbsp;register = template.Library()@register.filter(name=&#8217;cut&#8217;)def cut(value, arg):&nbsp;&nbsp; return value.replace(arg, &#8221;)<\/p>\n<p><strong>Writing Custom Template Tags<\/strong> &#8211; Tags are more complex than filters, because tags can do nearly<\/p>\n<p>anything.Chapter 4 describes how the template system works in a two-step process: compiling and rendering. To define a custom template tag, you need to tell Django how to manage both steps when it gets to your tag. When Django compiles a template, it splits the raw template text into <em>nodes<\/em>. Each node is an instance of django.template.Node and has a render() method. Thus, a compiled template is simply a list of Node objects.<\/p>\n<p>When you call render() on a compiled template, the template calls render() on each Node in its node list, with the given context. The results are all concatenated together to form the output of the template. Thus, to define a custom template tag, you specify how the raw template tag is converted into a Node (the compilation function) and what the node\u2019s render() method does.<\/p>\n<p><strong>Writing the Compilation Function<\/strong> &#8211; For each template tag it encounters, the template parser calls a Python function with the tag contents and the parser object itself. This function is responsible for returning a Node instance based on the contents of the tag.<\/p>\n<p>For example, let\u2019s write a template tag, {% current_time %}, that displays the current date\/time, formatted according to a parameter given in the tag, in strftime syntax (see http:\/\/www.djangoproject.com\/r\/python\/strftime\/). It\u2019s a good idea to decide the tag syntax before anything else. In our case, let\u2019s say the tag should be used like this:<\/p>\n<p>&lt;p&gt;The time is {% current_time &#8220;%Y-%m-%d %I:%M %p&#8221; %}.&lt;\/p&gt;<\/p>\n<p><strong>Note<\/strong> &#8211; Yes, this template tag is redundant\u2014Django\u2019s default {% now %} tag does the same task with simpler syntax. This template tag is presented here just for example purposes. The parser for this function should grab the parameter and create a Node object:<\/p>\n<p>from django import template&nbsp;def do_current_time(parser, token):&nbsp;&nbsp; try:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # split_contents() knows not to split quoted strings.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tag_name, format_string = token.split_contents()&nbsp;&nbsp; except ValueError:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; msg = &#8216;%r tag requires a single argument&#8217; % token.contents[0]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise template.TemplateSyntaxError(msg)&nbsp;&nbsp; return CurrentTimeNode(format_string[1:-1])<\/p>\n<p>There\u2019s actually a lot going here:<\/p>\n<ul>\n<li>parser is the template parser object. We don\u2019t need it in this example.<\/li>\n<li>contents is a string of the raw contents of the tag. In our example, it\u2019s &#8216;current_time&#8221;%Y-%m-%d%I:%M%p&#8221;&#8216;.<\/li>\n<li>The split_contents() method separates the arguments on spaces while keeping quoted strings together. Avoid using token.contents.split() (which just uses Python\u2019s standard string-splitting semantics). It\u2019s not as robust, as it naively splits on <em>all<\/em> spaces, including those within quoted strings.<\/li>\n<li>This function is responsible for raising template.TemplateSyntaxError, with helpful messages, for any syntax error.<\/li>\n<li>Don\u2019t hard-code the tag\u2019s name in your error messages, because that couples the tag\u2019s name to your function. split_contents()[0] will <em>always<\/em> be the name of your tag\u2014even when the tag has no arguments.<\/li>\n<li>The function returns a CurrentTimeNode (which we\u2019ll create shortly) containing everything the node needs to know about this tag. In this case, it just passes the argument &#8220;%Y-%m-%d %I:%M %p&#8221;. The leading and trailing quotes from the template tag are removed with format_string[1:-1].<\/li>\n<li>Template tag compilation functions <em>must<\/em> return a Node subclass; any other return value is an error.<\/li>\n<\/ul>\n<p><strong>Writing the Template Node<\/strong> &#8211; The second step in writing custom tags is to define a Node subclass that has a render() method. Continuing the preceding example, we need to define CurrentTimeNode:<\/p>\n<p>import datetime&nbsp;class CurrentTimeNode(template.Node):&nbsp;&nbsp;&nbsp; def __init__(self, format_string):&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.format_string = format_string&nbsp;&nbsp;&nbsp; def render(self, context):&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; now = datetime.datetime.now()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return now.strftime(self.format_string)<\/p>\n<p>These two functions (__init__ and render) map directly to the two steps in template processing (compilation and rendering). Thus, the initialization function only needs to store the format string for later use, and the render() function does the real work.Like template filters, these rendering functions should fail silently instead of raising errors. The only time that template tags are allowed to raise errors is at compilation time.<\/p>\n<p><strong>Registering the Tag<\/strong> &#8211; Finally, you need to register the tag with your module\u2019s Library instance. Registering custom tags is very similar to registering custom filters (as explained above). Just instantiate a template.Library instance and call its tag() method. For example:<\/p>\n<p>register.tag(&#8216;current_time&#8217;, do_current_time)<\/p>\n<p>The tag() method takes two arguments:<\/p>\n<ul>\n<li>The name of the template tag (string). If this is left out, the name of the compilation function will be used.<\/li>\n<li>The compilation function.<\/li>\n<\/ul>\n<p>As with filter registration, it is also possible to use register.tag as a decorator in Python 2.4 and above:<\/p>\n<p>@register.tag(name=&#8221;current_time&#8221;)def do_current_time(parser, token):&nbsp;&nbsp; # &#8230;&nbsp;@register.tagdef shout(parser, token):&nbsp;&nbsp; # &#8230;<\/p>\n<p>If you leave off the name argument, as in the second example, Django will use the function\u2019s name as the tag name.<\/p>\n<p><strong>Setting a Variable in the Context<\/strong> &#8211; The previous section\u2019s example simply returned a value. Often it\u2019s useful to set template variables instead of returning values. That way, template authors can just use the variables that your template tags set. To set a variable in the context, use dictionary assignment on the context object in the render() method. Here\u2019s an updated version of CurrentTimeNode that sets a template variable, current_time, instead of returning it:<\/p>\n<p>class CurrentTimeNode2(template.Node):&nbsp;&nbsp; def __init__(self, format_string):&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.format_string = format_string&nbsp;&nbsp;&nbsp; def render(self, context):&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; now = datetime.datetime.now()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context[&#8216;current_time&#8217;] = now.strftime(self.format_string)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return &#8221;<\/p>\n<p>Note that render() returns an empty string. render() should always return a string, so if all the template tag does is set a variable, render() should return an empty string. Here\u2019s how you\u2019d use this new version of the tag:<\/p>\n<p>{% current_time2 &#8220;%Y-%M-%d %I:%M %p&#8221; %}&lt;p&gt;The time is {{ current_time }}.&lt;\/p&gt;<\/p>\n<p>But there\u2019s a problem with CurrentTimeNode2: the variable name current_time is hard-coded. This means you\u2019ll need to make sure your template doesn\u2019t use {{ current_time }} anywhere else, because {% current_time2 %} will blindly overwrite that variable\u2019s value. A cleaner solution is to make the template tag specify the name of the variable to be set, like so:<\/p>\n<p>{% get_current_time &#8220;%Y-%M-%d %I:%M %p&#8221; as my_current_time %}&lt;p&gt;The current time is {{ my_current_time }}.&lt;\/p&gt;<\/p>\n<p>To do so, you\u2019ll need to refactor both the compilation function and the Node class, as follows:<\/p>\n<p>import re&nbsp;class CurrentTimeNode3(template.Node):&nbsp;&nbsp;&nbsp; def __init__(self, format_string, var_name):&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.format_string = format_string&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.var_name = var_name&nbsp;&nbsp;&nbsp; def render(self, context):&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; now = datetime.datetime.now()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context[self.var_name] = now.strftime(self.format_string)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return &#8221;<\/p>\n<p>def do_current_time(parser, token):&nbsp;&nbsp; # This version uses a regular expression to parse tag contents.&nbsp;&nbsp; try:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Splitting by None == splitting by spaces.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tag_name, arg = token.contents.split(None, 1)&nbsp;&nbsp; except ValueError:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; msg = &#8216;%r tag requires arguments&#8217; % token.contents[0]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise template.TemplateSyntaxError(msg)&nbsp;&nbsp;&nbsp; m = re.search(r'(.*?) as (\\w+)&#8217;, arg)&nbsp;&nbsp; if m:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fmt, var_name = m.groups()&nbsp;&nbsp; else:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; msg = &#8216;%r tag had invalid arguments&#8217; % tag_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise template.TemplateSyntaxError(msg)&nbsp;&nbsp;&nbsp; if not (fmt[0] == fmt[-1] and fmt[0] in (&#8216;&#8221;&#8216;, &#8220;&#8216;&#8221;)):&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; msg = &#8220;%r tag&#8217;s argument should be in quotes&#8221; % tag_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise template.TemplateSyntaxError(msg)&nbsp;&nbsp;&nbsp; return CurrentTimeNode3(fmt[1:-1], var_name)<\/p>\n<p>Now do_current_time() passes the format string and the variable name to CurrentTimeNode3.<\/p>\n<p><u>Parsing Until Another Block Tag<\/u> &#8211; Template tags can work as blocks containing other tags (think {% if %}, {% for %}, etc.). To create a template tag like this, use parser.parse() in your compilation function. Here\u2019s how the standard {% comment %} tag is implemented:<\/p>\n<p>def do_comment(parser, token):&nbsp;&nbsp; nodelist = parser.parse((&#8216;endcomment&#8217;,))&nbsp;&nbsp; parser.delete_first_token()&nbsp;&nbsp; return CommentNode()&nbsp;class CommentNode(template.Node):&nbsp;&nbsp; def render(self, context):&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return &#8221;<\/p>\n<p>parser.parse() takes a tuple of names of block tags to parse until. It returns an instance of django.template.NodeList, which is a list of all Node objects that the parser encountered <em>before<\/em> it encountered any of the tags named in the tuple. So in the preceding example, nodelist is a list of all nodes between {% comment %} and {% endcomment %}, not counting {% comment %} and {% endcomment %} themselves.<\/p>\n<p>After parser.parse() is called, the parser hasn\u2019t yet \u201cconsumed\u201d the {% endcomment %} tag, so the code needs to explicitly call parser.delete_first_token() to prevent that tag from being processed twice. Then CommentNode.render() simply returns an empty string. Anything between {% comment %} and {% endcomment %} is ignored.<\/p>\n<p><u>Parsing Until Another Block Tag and Saving Contents<\/u> &#8211; In the previous example, do_comment() discarded everything between {% comment %} and {% endcomment %}. It\u2019s also possible to do something with the code between block tags instead. For example, here\u2019s a custom template tag, {% upper %}, that capitalizes everything between itself and {% endupper %}:<\/p>\n<p>{% upper %}<\/p>\n<p>This will appear in uppercase, {{ your_name }}.<\/p>\n<p>{% endupper %}<\/p>\n<p>As in the previous example, we\u2019ll use parser.parse(). This time, we pass the resulting nodelist to Node:<\/p>\n<p>@register.tag<\/p>\n<p>def do_upper(parser, token):<\/p>\n<p>nodelist = parser.parse((&#8216;endupper&#8217;,))<\/p>\n<p>parser.delete_first_token()<\/p>\n<p>return UpperNode(nodelist)<\/p>\n<p>class UpperNode(template.Node):<\/p>\n<p>def __init__(self, nodelist):<\/p>\n<p>self.nodelist = nodelist<\/p>\n<p>def render(self, context):<\/p>\n<p>output = self.nodelist.render(context)<\/p>\n<p>return output.upper()<\/p>\n<p>The only new concept here is self.nodelist.render(context) in UpperNode.render(). This simply calls render() on each Node in the node list. For more examples of complex rendering, see the source code for {% if %}, {% for %}, {% ifequal %}, and {% ifchanged %}. They live in django\/template\/defaulttags.py.<\/p>\n<p><strong>Shortcut for Simple Tags<\/strong> &#8211; Many template tags take a single argument\u2014a string or a template variable reference\u2014and return a string after doing some processing based solely on the input argument and some external information. For example, the current_time tag we wrote earlier is of this variety. We give it a format string, and it returns the time as a string. To ease the creation of these types of tags, Django provides a helper function, simple_tag. This function, which is a method of django.template.Library, takes a function that accepts one argument, wraps it in a render function and the other necessary bits mentioned previously, and registers it with the template system. Our earlier current_time function could thus be written like this:<\/p>\n<p>def current_time(format_string):<\/p>\n<p>return datetime.datetime.now().strftime(format_string)<\/p>\n<p>register.simple_tag(current_time)<\/p>\n<p>In Python 2.4, the decorator syntax also works:<\/p>\n<p>@register.simple_tag<\/p>\n<p>def current_time(token):<\/p>\n<p>&#8230;<\/p>\n<p>A couple of things to notice about the simple_tag helper function are as follows:<\/p>\n<ul>\n<li>Only the (single) argument is passed into our function.<\/li>\n<li>Checking for the required number of arguments has already been done by the time our function is called, so we don\u2019t need to do that.<\/li>\n<li>The quotes around the argument (if any) have already been stripped away, so we receive a plain string.<\/li>\n<\/ul>\n<p><strong>&nbsp;Inclusion Tags<\/strong> &#8211; Another common template tag is the type that displays some data by rendering <em>another<\/em> template. For example, Django\u2019s admin interface uses custom template tags to display the buttons along the bottom of the \u201cadd\/change\u201d form pages. Those buttons always look the same, but the link targets change depending on the object being edited. They\u2019re a perfect case for using a small template that is filled with details from the current object. These sorts of tags are called <em>inclusion tags<\/em>. Writing inclusion tags is probably best demonstrated by example. Let\u2019s write a tag that produces a list of choices for a simple multiple-choice Poll object. We\u2019ll use the tag like this:<\/p>\n<p>{% show_results poll %}<\/p>\n<p>The result will be something like this:<\/p>\n<p>&lt;ul&gt;<\/p>\n<p>&lt;li&gt;First choice&lt;\/li&gt;<\/p>\n<p>&lt;li&gt;Second choice&lt;\/li&gt;<\/p>\n<p>&lt;li&gt;Third choice&lt;\/li&gt;<\/p>\n<p>&lt;\/ul&gt;<\/p>\n<p>First, we define the function that takes the argument and produces a dictionary of data for the result. Notice that we need to return only a dictionary, not anything more complex. This will be used as the context for the template fragment:<\/p>\n<p>def show_books_for_author(author):<\/p>\n<p>books = author.book_set.all()<\/p>\n<p>return {&#8216;books&#8217;: books}<\/p>\n<p>Next, we create the template used to render the tag\u2019s output. Following our example, the template is very simple:<\/p>\n<p>&lt;ul&gt;<\/p>\n<p>{% for book in books %}<\/p>\n<p>&lt;li&gt; {{ book }} &lt;\/li&gt;<\/p>\n<p>{% endfor %}<\/p>\n<p>&lt;\/ul&gt;<\/p>\n<p>Finally, we create and register the inclusion tag by calling the inclusion_tag() method on a Library object. Following our example, if the preceding template is in a file called polls\/result_snippet.html, we register the tag like this:<\/p>\n<p>register.inclusion_tag(&#8216;books\/books_for_author.html&#8217;)(show_books_for_author)<\/p>\n<p>As always, Python 2.4 decorator syntax works as well, so we could have instead written this:<\/p>\n<p>@register.inclusion_tag(&#8216;books\/books_for_author.html&#8217;)<\/p>\n<p>def show_books_for_author(show_books_for_author):<\/p>\n<p>&#8230;<\/p>\n<p>Sometimes, your inclusion tags need access to values from the parent template\u2019s context. To solve this, Django provides a takes_context option for inclusion tags. If you specify takes_context in creating a template tag, the tag will have no required arguments, and the underlying Python function will have one argument: the template context as of when the tag was called.<\/p>\n<p>For example, say you\u2019re writing an inclusion tag that will always be used in a context that contains home_link and home_title variables that point back to the main page. Here\u2019s what the Python function would look like:<\/p>\n<p>@register.inclusion_tag(&#8216;link.html&#8217;, takes_context=True)<\/p>\n<p>def jump_link(context):<\/p>\n<p>return {<\/p>\n<p>&#8216;link&#8217;: context[&#8216;home_link&#8217;],<\/p>\n<p>&#8216;title&#8217;: context[&#8216;home_title&#8217;],<\/p>\n<p>}<\/p>\n<p><strong>Note<\/strong> &#8211; The first parameter to the function <em>must<\/em> be called context.<\/p>\n<p>The template link.html might contain the following:<\/p>\n<p>Jump directly to &lt;a href=&#8221;{{ link }}&#8221;&gt;{{ title }}&lt;\/a&gt;.<\/p>\n<p>Then, anytime you want to use that custom tag, load its library and call it without any arguments, like so:<\/p>\n<p>{% jump_link %}<\/p>\n\n\n<p><a href=\"https:\/\/www.vskills.in\/certification\/tutorial\/certified-django-developer\/\" target=\"_blank\" rel=\"noreferrer noopener\">Back to Tutorial<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Now that you understand a bit more about the internals of the template system, let\u2019s look at how to extend the system with custom code. Most template customization comes in the form of custom template tags and\/or filters. Although the Django template language comes with many built-in tags and filters, you\u2019ll probably assemble your own&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"categories":[8655],"tags":[8787],"class_list":["post-75728","page","type-page","status-publish","hentry","category-django-web-development","tag-extending-the-template-system"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Extending the Template System - Tutorial<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.vskills.in\/certification\/tutorial\/extending-the-template-system\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Extending the Template System - Tutorial\" \/>\n<meta property=\"og:description\" content=\"Now that you understand a bit more about the internals of the template system, let\u2019s look at how to extend the system with custom code. Most template customization comes in the form of custom template tags and\/or filters. Although the Django template language comes with many built-in tags and filters, you\u2019ll probably assemble your own...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.vskills.in\/certification\/tutorial\/extending-the-template-system\/\" \/>\n<meta property=\"og:site_name\" content=\"Tutorial\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/vskills.in\/\" \/>\n<meta property=\"article:modified_time\" content=\"2024-04-12T08:47:15+00:00\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"17 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/extending-the-template-system\/\",\"url\":\"https:\/\/www.vskills.in\/certification\/tutorial\/extending-the-template-system\/\",\"name\":\"Extending the Template System - Tutorial\",\"isPartOf\":{\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#website\"},\"datePublished\":\"2020-01-20T06:23:43+00:00\",\"dateModified\":\"2024-04-12T08:47:15+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/extending-the-template-system\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.vskills.in\/certification\/tutorial\/extending-the-template-system\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/extending-the-template-system\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.vskills.in\/certification\/tutorial\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Extending the Template System\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#website\",\"url\":\"https:\/\/www.vskills.in\/certification\/tutorial\/\",\"name\":\"Tutorial\",\"description\":\"Vskills - A initiative in elearning and certification\",\"publisher\":{\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.vskills.in\/certification\/tutorial\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#organization\",\"name\":\"Vskills\",\"url\":\"https:\/\/www.vskills.in\/certification\/tutorial\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.vskills.in\/certification\/tutorial\/wp-content\/uploads\/2017\/07\/vskills-min-logo.jpg\",\"contentUrl\":\"https:\/\/www.vskills.in\/certification\/tutorial\/wp-content\/uploads\/2017\/07\/vskills-min-logo.jpg\",\"width\":73,\"height\":55,\"caption\":\"Vskills\"},\"image\":{\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/vskills.in\/\",\"https:\/\/x.com\/vskills_in\",\"https:\/\/www.linkedin.com\/company-beta\/1371554\/\",\"https:\/\/www.youtube.com\/channel\/UCMWnscxPwRF_PqXo9B7q_Tw\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Extending the Template System - Tutorial","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.vskills.in\/certification\/tutorial\/extending-the-template-system\/","og_locale":"en_US","og_type":"article","og_title":"Extending the Template System - Tutorial","og_description":"Now that you understand a bit more about the internals of the template system, let\u2019s look at how to extend the system with custom code. Most template customization comes in the form of custom template tags and\/or filters. Although the Django template language comes with many built-in tags and filters, you\u2019ll probably assemble your own...","og_url":"https:\/\/www.vskills.in\/certification\/tutorial\/extending-the-template-system\/","og_site_name":"Tutorial","article_publisher":"https:\/\/www.facebook.com\/vskills.in\/","article_modified_time":"2024-04-12T08:47:15+00:00","twitter_misc":{"Est. reading time":"17 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.vskills.in\/certification\/tutorial\/extending-the-template-system\/","url":"https:\/\/www.vskills.in\/certification\/tutorial\/extending-the-template-system\/","name":"Extending the Template System - Tutorial","isPartOf":{"@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#website"},"datePublished":"2020-01-20T06:23:43+00:00","dateModified":"2024-04-12T08:47:15+00:00","breadcrumb":{"@id":"https:\/\/www.vskills.in\/certification\/tutorial\/extending-the-template-system\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.vskills.in\/certification\/tutorial\/extending-the-template-system\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.vskills.in\/certification\/tutorial\/extending-the-template-system\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.vskills.in\/certification\/tutorial\/"},{"@type":"ListItem","position":2,"name":"Extending the Template System"}]},{"@type":"WebSite","@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#website","url":"https:\/\/www.vskills.in\/certification\/tutorial\/","name":"Tutorial","description":"Vskills - A initiative in elearning and certification","publisher":{"@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.vskills.in\/certification\/tutorial\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#organization","name":"Vskills","url":"https:\/\/www.vskills.in\/certification\/tutorial\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#\/schema\/logo\/image\/","url":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-content\/uploads\/2017\/07\/vskills-min-logo.jpg","contentUrl":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-content\/uploads\/2017\/07\/vskills-min-logo.jpg","width":73,"height":55,"caption":"Vskills"},"image":{"@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/vskills.in\/","https:\/\/x.com\/vskills_in","https:\/\/www.linkedin.com\/company-beta\/1371554\/","https:\/\/www.youtube.com\/channel\/UCMWnscxPwRF_PqXo9B7q_Tw"]}]}},"_links":{"self":[{"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/pages\/75728","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/comments?post=75728"}],"version-history":[{"count":4,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/pages\/75728\/revisions"}],"predecessor-version":[{"id":83366,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/pages\/75728\/revisions\/83366"}],"wp:attachment":[{"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/media?parent=75728"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/categories?post=75728"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/tags?post=75728"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}