Hey Guys !
Well, in a previous blog i wrote about creating your own context variable. To take that a step further, why don't we create our own template tags. So, what is a template tag ? It is a built-in django function that returns an output.
Now, you might have some doubts as to why you would need a template tag instead of a context variable, since, they're both functions and they both return a value. Right? Well, if that thought didn't come to mind, the reason for creating your own template tag is that, you can actually pass a value to the function upon which you could do your processing, while you could not with the context variable.
Why and Where do you need your own template tags
Before we go and create our own template tags, first, you need to look in the django official documentation, there's a high probability that the template tag that you're looking for might be in there.
In this blog, i will consider my project to be an online shopping app and my models will include the products on sale and the corresponding reviews on those products. So, my models.py file will look like this.
from django.db import models
from django.contrib.auth.models import User
class Product(models.Model):
name = models.CharField(max_length=50)
description = models.CharField(max_length=200)
sold_by = models.ForeignKey(User)
price = models.IntegerField()
def __str__(self):
return self.name
class Review(models.Model):
content = models.CharField(max_length=100)
reviewed_on = models.ForeignKey(Product)
reviewed_by = models.ForeignKey(User)
def __str__(self):
return self.content
So, in my product listing page, i want to be able to view the products and the review count for each product there. You could write a ORM query for it in your views.py file but what if you need the same count in each of the dedicated product pages, you would have to repeat that code. Unless, you had a function which accepts the product id and returns the count of reviews of that specific product. You could use that function anywhere. This function is our template tags and we will be using it to solve this problem.
Creating your own template tags using the simple_tag
First, you need to create a folder inside your app called templatetags and create a file named _init_.py . This will initiliase our templatetags folder as a python package, basically, django will consider it as part of its own project folder architecture.
Secondly, lets create a python file with any name, for this blog, i'll name it product_tags.py. Now, we are going to be creating our own template tags using the simple_tag.
from django import template
from your_app.models import Product, Review
register = template.Library()
@register.simple_tag
def calc_review_count(product_id):
product = Product.objects.get(id=product_id)
reviews = Review.objects.filter(reviewed_on=product)
return reviews.count()
Using our custom template tags in our templates
Now, your template tags is ready to be used in your html files. So lets create a ListView pretty quickly in my views.py file.
from django.views.generic import ListView
from .models import Product
class ProductListing(ListView):
template_name = 'product_list.html'
model = Product
context_object_name = 'products'
Finally, lets go ahead and create our html file that i named product_list.html.
{% load product_tags %} <!-- Loading the file we defined our template tags in -->
<div>
<table>
<thead>
<tr>
<th>Name</th>
<th>Price</th>
<th>Sold By</th>
<th>Reviews</th>
</tr>
</thead>
<tbody>
{% for pdt in products %}
<tr>
<td>pdt.name</td>
<td>pdt.price</td>
<td>pdt.sold_by</td>
<td>{% calc_review_count pdt.id %}</td> <!-- our template tag -->
</tr>
{% endfor %}
</tbody>
</table>
</div>
Now, in a url that you configured, our template will show us the product listing and the review count for each of those products. Do note that we do not need closing template tags for template tags created using the simple_tag.
So what did you think about creating your own template tags ? Where do you think, you can use this ? Let me know.
Thanks and Have a Great Day !
Top comments (2)
Hey can I use a template tag(custom) to count the number of downloads on a given file?
Sure you can do that.