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 %}
});