Using Template Specific JavaScript in Django - javascript

I have a base_generic.html page in django that has the standard UI elements (navbar, footer, etc.), and I have a list.html page which extends the base_generic.html page. The list.html page is using a javascript function that is only used in this page, but for it to work, I have to include it in the base_generic.html page.
How can I include this javascript function in list.html using Django's built-in template tags and features?
Should I use {% verbatim %} or {% scripts %} or another tag template?
Should I include this inline with the {% block content %} that has the html for this django template, or should I place it before or after the {% block content %}?

You have several ways of accomplish what you want:
Just add the javascript snippet inside the {% block content %}
{% block content %}
my javascript();
{% endblock content %}
Use the include statement to a file with your javascript, again, inside the {% block content %}
{% include 'my_javascript.html' %}
In this way, you can reuse your javascript code on other pages.
Create a new block in base_generic.html, like:
{% block my_javascript %}{% endblock my_javascript %}
And in you child template, add the javascript as told in the first points iside these tags, in this case it can be outside or inside the {% block content %}.

An alternative would be pass the path for the js file in your views.py:
context = {
'scripts_to_include':['/static/js/my_js_file.js']
}
You can obviously include multiple js files here. Then, in your template:
{% if scripts_to_include %}
{% for script_url in scripts_to_include %}
<script src="{{script_url}}"></script>
{% endfor %}
{% endif %}
I like this, cause the js files can still be stored in a directory (instead of putting it right into html), JS files are also reusable.

Related

Separating JavaScripts file in symfony4 twig templates

I have a question about, how to separate a loading specify javascript file of specify template twig file.
I got for example admin.html.twig which extends base.html.twig, in base i got
{% block javascripts %}
<script src="/assets/js/core/jquery.min.js"></script>
<script src="/assets/js/core/popper.min.js"></script>
<script src="/assets/js/core/bootstrap-material-design.min.js"></script>
<script src="/assets/js/plugins/perfect-scrollbar.jquery.min.js"></script>
<script async defer src="https://buttons.github.io/buttons.j"></script>
<script src="/assets/js/plugins/chartist.min.js"></script>
<script src="/assets/js/plugins/bootstrap-notify.js"></script>
<script src="/assets/js/material-dashboard.min.js"></script>
<script src="/assets/demo/jquery.sharrre.js"></script>
<script src="/assets/js/sparkline.js"></script>
<script src="/assets/js/plugins/chartjs.min.js"></script>
{% endblock %}
and I got next file like dashboard.html.twig which extends a admin.html.twig file, and my question is that in dashboard.html.twig file i got at the a little writed-self small javascript code, and this javascript of course use a jquery library but this library i loaded in base.html.twig file a next of my selfwrited script which is in dashboard.html.twig.
My question is, how i can for example load my small code of javascript (of course i can save it in separated file like mycode.js) but how to load only when this route of dashboard.html.twig file i used and after jquery is loaded ? becouse in another routers i dont need this mycode.js so I dont wanna put it to base.html.twig file in javascript block, any idea ?
If dashboard directly extends admin then u can do the following to ensure to load all the admin scripts and to add the dashboard specific script:
{% extends "admin.html.twig" %}
{% block javascripts %}
{{ parent() }} {# execute the parent block, thus loading all scripts in admin #}
<script src="/assets/js/dashboard/mycode.js"></script>
{% endblock %}
You can dived
{% extends "admin.html.twig" %} {# use only in case your all templates are at the same places like app/Resources/views/admin.html.twig #}
{% block javascripts %}
{{ parent() }} {# loads the parent javascript block, from the template you are extending in first line. #}
<script src="/assets/js/dashboard/code.js"></script>
{% endblock %}
in case you are trying to extend a template from another bundle then you can use this
{% extends "YourBundleName:Default:admin.html.twig" %} {# YourControllerRelativeName just in case your view structure is like views/Default/admin.html.twig#}
{% block javascripts %}
{{ parent() }} {# loads the parent javascript block, from the template you are extending in first line. #}
<script src="/assets/js/dashboard/code.js"></script>
{% endblock %}
to the better understanding you should read a little here:
https://symfony.com/doc/2.8/templating.html
Note:- in the documents you should change version as per your current version.
I would suggest the following solution.
Declare the following block in base.html.twig after {% block javascripts %}{% endblock %}
{% block javascript_page %}{# specific code for current page #}{% endblock %}
Then in your page you can include page specific scripts
{% extends "admin.html.twig" %} or {% extends "base.html.twig" %}
{% block javascript_page %}
<script src="/assets/js/pages/my_page.js"></script>
{% endblock %}
Although answer by DarkBee is also correct but in this way you don't have to worry about calling {{ parent() }} in each page.

Django extended template is not loading base JS at time

I've in Django 1.11 a base.html which contains all the scripts references.
Then, I've another page.html that extendes base.html with {% extends base.html %} and {% block content %} / {% endblock content %} tags.
Well. In base.html I've a reference to Chartjs.js plugin. In page.html, if I try to call to Chart() function or just $ jquery, I get "function is not defined". If I open console debugger and try to call $ or just Chart(), it works. So I think that there's a problem with loading time. The page.html is rendered before the js are downloaded or requested!
How can I solve it? I've done it before, I don't know what could be the problem.
Thanks!
Without your code showing, hard to tell. Based on what you wrote, perhaps you forgot to put a block and block.super to get the parent (base.html's) Chartjs reference.
This should be in your page.html at the bottom after your {% endblock content %} tag. See example below (using DataTables as example since your code is not shown):
</div>
{% endblock content %}
{% block javascript %}
{{ block.super }}
<script type="application/javascript">
$(document).ready(function () {
$('#table').DataTable({
responsive: true,
});
});
</script>
{% endblock javascript %}
Base.html would have the js section enclosed in
{% block javascript %} …. {% endblock javascript %}

Include css and/or script from template tag

I have a Django app that uses a template tag to process a wordpress style shortcode. My code is based on https://github.com/emilbjorklund/django-template-shortcodes/blob/master/shortcodes but I have added my own parser. The shortcode is basically an image album e.g. [album view=slideshow id=1], where the view can either be a slideshow (Bootstrap Carousel) or Gallery (Lightbox). My parser looks like:
def parse(tag_atts, tag_contents=None):
#Check our id is a digit.
tag_atts['content'] = "Album Short Tag Error"
if tag_atts['id'].isdigit:
#try:
# Get the data from the album
album = Album.objects.get(pk = tag_atts['id'] )#.select_related()
images = Image.objects.filter(album__id=album.id)
if tag_atts['view']=='gallery':
return makeGallery(album,images,tag_atts)
elif tag_atts['view']=='slideshow':
return makeSlideshow(album,images,tag_atts)
else:
context = Context(tag_atts)
t = Template("""{{ content }}""")
return t.render(context)
The makeGallery and makeSlideshow functions just process the shortcode and its attributes returning a rendered template with all the required HTML like the given else clause but with more complexity (see the github parser examples for ideas).
Everything is working fine but I need to include a custom css file and javascript file for the lightbox in the instance that its a gallery view that has been requested. At the moment this is included in the main page template file using a custom block but this means that its always there regardless of whether the shortcode exists or a gallery has been requested.
What would be the appropriate method of telling Django to include these additional files from inside the template tag only when required?
I'm loathed to add an additional 'checker' tag that parses the page content in the customcss header block to see whether to include it and again for the customscript block in the footer.
I look forward to hearing from more experience Djangooists.
Chris
Use template inheritance, per the django docs. Please note that these are all very generic examples, it should be enough to get you going though. Be sure to check out the docs I linked above.
base_page.html
# pretend your standard html opening stuff is here.
# Put your base css file(s) here. Things you want for every page.
{% block css_block %}
# Leave this empty for now.
{% endblock %}
{% block body %}
# If all your pages have the same base layout, put it here.
{% endblock %}
# Put all javascript files here that are needed on all pages.
{% block js_block %}
# Leave this empty for now.
{% endblock %}
#pretend your ending html is here
gallery_template.html
{% extends 'base_page.html' %}
{% block css_block %}
<link rel="stylesheet" href="gallery.css"/>
{% endblock %}
{% block js_block %}
<script src="gallery.js"></script>
{% endblock %}
slideshow_template.html
{% extends 'base_page.html' %}
{% block css_block %}
<link rel="stylesheet" href="slideshow.css"/>
{% endblock %}
{% block js_block %}
<script src="slideshow.js"></script>
{% endblock %}
your view functions
#camelcase is fine, consistency is important though.
def make_gallery(album,images,tag_atts)
#do things here
return render_to_response('path/to/gallery_template.html')
def make_slideshow(album,images,tag_atts)
#do things here
return render_to_response('path/to/slideshow_template.html')

Django, recommended way to declare and solve JavaScript dependencies in blocks

Is there a good, performant and/or recommended way to declare and provide JS dependencies for blocks in Django templates?
Basically what I want to do is this:
In a Django template file containing a block, declare: I need JS library X to function.
In the tag of the page, upon rendering the page, insert a script tag for this library, but never more than once.
The reasons:
Minimize number of unnecessary JS libraries included in the page to keep load time acceptable in old browsers. (some libs like jquery-ui are very heavyweight for old IEs)
Prevent potentially repeated loading of JS libraries, both for performance and bug-prevention reasons. This happens when you have repeated blocks or multiple blocks including the same JS lib.
I've seen some potential solutions to this but none of them were very compelling from a performance or clarity perspective, so far.
You could use the {% include %} template tag. If you load js into the header you could do something like this:
base.html
<head>
<title>XXXX</title>
...
<script type="text/javascript" src="{{ STATIC_URL}}js/jquery.js"></script>
...
{% block site_header %}{% endblock %}
</head>
other.html
{% extends "base.html" %}
{% block site_header %}
...
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/urlify.js"></script>
..
{% endblock %}
You will have to adjust templates/pathes/etc. to your needs.
For this purpose, I personnaly use Django
Sekizai.
In my base template I have this block :
{% load sekizai_tags %}
<body>
# your own logic here
{% with_data "js-data" as javascripts %}
{% for javascript in javascripts %}
<script type="text/javascript"
src="{{ STATIC_URL }}{{ javascript }}" ></script>
{% endfor %}
{% end_with_data %}
</body>
Then, in my included or extending templates :
{% load sekizai_tags %}
{% add_data "js-data" "myapp/js/script.js" %}
Note you can define multiple blocks, and also use it for CSS, which is very
convenient.
Files added with "add_data" tag will never be repeated even if added several
times.

Use Django template tags in jQuery/Javascript?

Can I use Django's template tags inside Javascript? Like using {% form.as_p %} in jQuery to dynamically add forms to the page.
Yes, I do it frequently. Your javascript has to be served through django, but if you just have it in the html header as inline javascript you'll be fine.
E.g: I use this to put prefix on a dynamic formset I use.
{% extends "base.html" %}
{% block extrahead %}
<script type="text/javascript">
$(document).ready(function() {
{# Append fields for dynamic formset to work#}
{% for fset, cap, _, tid in study_formsets.fset_cap_tid %}
$(function() {
$('.form_container_{{ tid }}').formset({
prefix: '{{ fset.prefix }}',
formCssClass: '{{ tid }}',
extraClasses: ['myrow1', 'myrow2']
});
});
{% endfor %}
});
</script>
{% endblock %}
Note in "base.html" I have a html head where the jquery libraries are loaded, that contains {% block extrahead %}{% endblock %}.
You can't use Django's template tags from your Javascript code if that's what you mean. All the Django variables and logic stop existing after the template has been rendered and the HttpResponse has been sent to the client. At that moment when Javascript executes, the client (browser) has no notion the variables you rendered the template with (such as "form").
What you can do is have Javascript modify your HTML page using chunks of HTML that were rendered by your Django template.
If you want to generate HTML on client side, I'd recommend to look at client side tempalte libraries (eg. JQuery Templates - use those with the {% verbatim %} templatetag).
If you want to use variables inside your rendered javascript I (that's my opnion), think it's a bad idea. But if all you want is to generate URL for your views, media and static files, I do this a lot.
Take a look to this github: jscssmin
Yes, you can use`
Example : `{{ user.username }}`
Be sure this is not single quotes but '(back tick / back quote)

Categories