Wednesday, March 23, 2022

How to use a Python variable in an external Javascript (Django)

One way to use a Python variable in an external Javascript is to declare the JS variable in the HTML template through context object, then pass this variable to the external script code :

<script type="text/javascript">
js_var_from_dj = "{{ django_var }}"
</script>

<script src="{% static "js/js_file.js" %}" type="text/javascript"></script>

 

js_file.js :

function functionA(){
// using the variable declared outside this js file
inner_js_var = js_var_from_dj ;
}

 

What if  instead of using HTML template to pass the Django context variable, we inject the variable directly into the external Javascript code ? 

This is actually possible, the trick here is to to wrap the original JS file in a View, and use that view to render the JS file as a Django template.

Our js_file become :

function functionA(){
   //using the Django context variable
   inner_js_var = {{django_var}} ;
}

and the Django views.py

def js_wrapper(request):
    django_var = "a message to js"
    context_for_js = {'django_var ': django_var}
    return render(request, 'path_to_template_folder/js_file.js', context_for_js ,"application/javascript")

 We add the view to the urls list :

urlpatterns = [
          path('js_wrapper.js', js_wrapper, name = "js_wrapper.js"),
         ]
and finally the external JS file would be declared like :

<script src="{% static "js_wrapper.js" %}" type="text/javascript"></script>

 

Exploiting Javascript code as Django template will potentially elevate client-side code capabilities.

A perfect use case is service worker where you want to setup a set of pages to be pre-cached dynamically, so to avoid hard coded html links to those pages. You can define the list of pages, server-side, and send it to the service worker in a form of a list.

Let's say you want to preload web pages with their specifications for a given user, you can then define the view where your retrieve the product list :

def sw_workbox(request):
      product_list = Product.objects.filter(user=request.user)
      context = {'product_list': product_list}
      return render(request, 'sw_workbox.js', context,"application/javascript") 

and then pass the pages links to precacheAndRoute():

workbox.precaching.precacheAndRoute([
  {% for product in
product_list%}    
     {url: '{% url 'your_app_name:productModel_change' product.id  %}'},
  {% endfor %}
});






No comments:

Post a Comment

What do you think ?

Posts