Creating custom template tags in Django

Sometimes existing templates tags are not enough for rebellious developers. They need to create custom template tags to use. In this article we are discussing step by step process to create and use custom template tags in django.

Template Tags:
If all the tags are related to app then bundle them inside that app, otherwise you may create a new app and then add newly created app to INSTALLED_APPS.
Steps to create custom template tags:
  • Create a new directory inside your app and name it 'templatetags'.
  • Create __init__.py  file inside this newly created directory.
  • Create tags file. Lets name is custom_template_tag.py
  • Import template.
  • All the tags should be registered to template.library  instance.
  • For registering tags, create a module level variable, lets name it library . So on the top of file , after import statements write register = template.library()  .
  • Now lets create a very simple tag to get random number in template. For this you need to import randint .
  • write code to generate random number and register that function with library. Complete code should look like below.
from django import template
from random import randint


register = template.Library()


@register.simple_tag
def random_number():
    return randint(0,999)
 
How to use custom tag in django templates:
Now when we have created custom tag and registered it with library, we can use it in templates. Load the tag class in your template before using any template. {% load custom_template_tags %} now use custom tag any where in your html. {% random_number %} . This will print a random number at the same place. you can store the output of tag in some variable can can use to anywhere in template. {% random_number as rnd %} now any where in template use {{rnd}} .
Things to take care of to make custom tags work:
  • Make sure you restarted the development server.
  • Directory name must be templatetags .
  • __init__.py  must be present in directory.
  • App where templatetags  directory is created must be present in installed apps.
  • Load the tag file in the template file where tag will be used. Loading file in parent template and then expecting it would be available to all child templates, would not work. Because zen of python.
  • If tag still not working, remove all .pyc  files.
  If it is still not working for you, please comment.

How to use AJAX with Django

AJAX is an acronym for Asynchronous JavaScript and XML. It is a group of inter-related technologies like JavaScript, DOM, XML, HTML, CSS etc. AJAX allows you to send and receive data asynchronously without reloading the web page.

At some point in your project development process you will need AJAX to execute some task. One fine example could be checking username availability on signup form.

We will discuss same scenario here and will guide you through the step by step process of using AJAX with Django.


How to use AJAX in Django:

So as per scenario discussed above, first we need to create a form with username field along with other fields. Use this code inside your form for login/username. 


<label for="login" class="col-md-2 control-label">Login</label>
<div class="col-md-4">
	<input type="text" class="form-control input-sm" name="login" id="login" placeholder="Login or Username" required="True" onkeyup="check_login(this);return false;" data-url="{% url "myapp_name:check_login" %}"/>
	{% csrf_token %}
</div>
<div class="col-md-6 col-sm-6" style="color:red;display:none;margin-top: 4px;"  id="login_not">
	<span class="glyphicon glyphicon-remove"></span> Username already taken.
</div>
<div class="col-md-6 col-sm-6" style="color: green;display: none;margin-top: 4px;" id="login_ok">
	<span class="glyphicon glyphicon-ok"></span> Username available.
</div>


We have created a input type of text which is a required field in form. On keyup event on this input field, we will call check_login function.

We are passing input field as parameter to this javascript function. So whenever text inside this input field changes, check_login function is triggered.

You can see an additional attribute data-url of input field. This is the URL where we send request from AJAX. We can hardcode this URL in javascript code but that won't be a good practice. Python/Django code should be limited to HTML only and should not be present in javascript.

We have also included csrf_token below the input field. CSRF token is required for all POST requests in Django. There are other ways to get the csrf token but that is out of scope of this article and hence we are going with this easy method.


Javascript/AJAX Code:

function check_login(element) {
	$("#login_ok").hide();
	$("#login_not").hide();
	login = $(element).val();
	if (login == "") {
		return;
	}
	$.ajax({
		url : $(element).attr("data-url"),
		data : {
			"csrfmiddlewaretoken" : $(element).siblings("input[name='csrfmiddlewaretoken']" ).val(),
			"login":login
		},
		method: "POST",
		dataType : "json",
		success : function (returned_data) {			
			if (returned_data.is_success) {
				$("#login_ok").show();
			} else {
				$("#login_not").show();
			}
		}
	});
}


On any text change in input field, check_login method is triggered.

Let see line by line, what is happening inside this function.

First we hide both the div where success/failure messages are being displayed. By default these divs are hidden when page is loaded first time. But as soon as you enter something in input field, one or the other div is displayed with message based on result received from ajax request.

Then we get the value of input field and if it is null/blank we do nothing and return from here.

Then we make ajax call with parameters. URL is picked from data-url attribute of input field.

In data, we are sending csrf_token and login/username. We defined method as post and then defined actions to be taken on success or error response.

If is_success variable in returned_data is set, then we show the div with success message else we show the div with error message.


Django code to handle the Ajax request:

First make sure you have URL (data-url in html code) in URL patterns.

In the view function check for availability of username and return appropriate JsonResponse.

def check_login(request):
    if request.method == "GET":
        raise Http404("URL doesn't exists")
    else:   
        response_data = {}
        login = request.POST["login"]
        user = None
        try:
            try:
                user = UserModel.objects.get(login = login)
            except ObjectDoesNotExist as e:
                pass
            except Exception as e:
                raise e
            if not user:
                response_data["is_success"] = True
            else:
                response_data["is_success"] = False
        except Exception as e:
            response_data["is_success"] = False
            response_data["msg"] = "Some error occurred. Please let Admin know."

        return JsonResponse(response_data)
Import the required modules and models.


Code on Github:

In one of previous article we developed a Hello World Django project. Here we have extended the same project and added the AJAX example in it. Code is available on Github.

Github URL : https://github.com/anuragrana/ajax_in_django


Please comment in case of any issue.



How to Track Email Opens Sent From Django App

In this article we will see how to track the Email opens for the emails sent from your Django App.

This will help us in accumulating the information such as:
 - who opened the email
- when was email opened
- what is the open rate, i.e. how many user opened the email
- what is the time when most of the users check their emails.


Sending Email:

We have covered this part in detail in below articles.

You may use any of these methods to send an email.
- Sending bulk emails using mailgun api
- Sending email using office 365
- Sending email using Gmail


Create the HTML body for email:

# using template to generate the email content
template = get_template("testapp/email.html")
context_data = dict()

# pass the variable image_url to template
# image_load is the URL name. see below
context_data["image_url"] = equest.build_absolute_uri(reverse("image_load"))
html_text = template.render(context_data)
plain_text = strip_tags(html_text)


In the email template email.html  , at the end of the content, insert the below code.

<img src="{{image_url}}" height="0px" width="0px"/>


This is an image of 0 by 0 pixels, which will not be visible in email but will hit the URL image_load  on our server when email is loaded.


Image src URL :

This is the URL which will be used as source of the image in email and will receive the hit whenever email will be opened.

Create a url in urls.py  file of your app.

url(r'^image_load/$', views.image_load, name='image_load'),


Create a view image_load  in views.py  file.

from django.http import HttpResponse
from PIL import Image

def image_load(request):
    print("\nImage Loaded\n")
    red = Image.new('RGB', (1, 1))
    response = HttpResponse(content_type="image/png")
    red.save(response, "PNG")
    return response


This view is creating and returning an image as response to url image_load.


Testing:

Now send the email and open it. As soon as you open the email, you will receive a hit on the image_load  url.

This will NOT work on localhost. So I created a test app for free on pythonanywhere server (it took me just 5 minutes) and used the URL from there.

Screenshot from


When I opened the test email, I could see the output printed in server logs.


Screenshot from  


When sending emails to multiple users, append the encrypted userId or emailId to the image source URL so that you can track who opened the email.


Try this and let us know your views.      



SUBSCRIBE
Please subscribe to get the latest articles in your mailbox.



Recent Posts: