Django-compressor and template inheritance - django

I'm using the django-compressor app in Django 1.2.3 to minify and merge a number of included CSS and JS files. In a base template, I have
{% load compress %}
{% compress js %}
{% block js %}
<script type="text/javascript" src="/site_media/js/jquery.query-2.1.7.js">
{% endblock %}
and in a child,
{% block js %}
{{block.super}}
<script type="text/javascript" src="/site_media/js/jquery.validate.min.js">
{% endblock %}
When the templates render, the first script tag is correctly minified, but the second isn't. In similar scenarios, I've confirmed that the issue is inheritance.
I don't want to keep using compress tags in child templates, because half the point of using this app is to merge the files and and cut back on the HTTP requests. Am I missing something? Is there another solution I should look into?

I use django-compressor with Django 1.2, and I set it up like this:
{% compress js %}
<script type="text/javascript" src="{{ MEDIA_URL }}js/jquery-1.4.2.min.js"></script>
{% block extra_compressed_js %}{% endblock %}
{% endcompress %}
{% block external_js %}{% endblock %}
And with my extra_compressed_js block I will often use the method you described, with {{ block.super }} to add more js through inheritance. It works for me without any trouble. One thing that you have to be careful about is that all the JS to compress needs to be available on the local filesystem. That's why I have a separate external_js block, for JS that comes from an outside source.
It sounds to me like something else is going on. Make sure your copy of compressor is up to date, and then check on your inheritance to make sure it's actually working correctly. One way to do this is by setting COMPRESS=False in your settings and making sure that all of the javascript that you want included actually shows up in the rendered template.

I don't know if this will work, but it seems worth a try:
First have these blocks in your base template:
{% compress js %}
{% block js %}
{% endblock %}
{% endcompress %}
{% compress css %}
{% block css %}
{% endblock %}
{% endcompress %}
and then in a given child template:
{% block js %}
{{ block.super }}
<script type="text/javascript" src="/site_media/js/jquery.query-2.1.7.js">
{% endblock %}
Always use block.super. Like I said, I don't know if it will work, but it might.

Related

How to use JavaScript in included components in Django?

In short, how to use JavaScript in the component that will be then included in the main page?
A standard approach in Django templates is to create a base.html template and then extend it. That base template usually has blocks like content, extra_js, and extra_css. The extended template looks like
{% extend 'base.html' %}
{% block content %}
<div>
some content
</div>
{% endblock %}
{% block extra_js %}
# some js code here
{% endblock %}
I need to create a component that will be included on several pages and I need to use JavaScript inside that component. I know that it will be included only on pages that extend base.html, the page that includes it will look like
{% extend 'base.html' %}
{% block content %}
<div>
{% include 'component.html' %}
</div>
{% endblock %}
{% block extra_js %}
# some js code here
{% endblock %}
However, component.html knows nothing about extra_js block because it doesn't extend base.html, I cannot use that block in component.html, and if I just put some JavaScript code in it then after the template is rendered any JavaScript in component.html will end up being in the middle of the body of the document, will be executed before libraries like jQuery are imported and will not work. What is the right way to work around it?

Django: Frequent use of include template tag - how much is too much?

I noticed that I started using include template a lot. One of my template files has 20+ include tags.
Some of them are for modal dialogs that in turn have include for different form field sets. I am also using basically the same buttons with different data attributes so these are also done with include tags. Some my "fragments" that I use with include have around only five lines of HTML code.
I worry if this is too much and can negatively affect performance (since Django loads another files, etc..)
For example whis is markup of one of my HTML fragments I am using with include:
<div class="form-group">
<input type="url" class="form-control" id="video-link-input" name="video_link"
placeholder="YouTube link">
</div>
<input type="hidden" id="video_id" name="video_id" value="">
<img class="img-fluid img-thumbnail" id="video-img-preview">
Hope the question is not too broad. I would just like to avoid possible bad practice.
Overly fragmented templates will impact your performance, but not because Django loads files.
With the default settings, Django caches template files when DEBUG=False:
django.template.loaders.cached.Loader
...
This loader is automatically enabled if OPTIONS['loaders'] isn’t
specified and OPTIONS['debug'] is False (the latter option defaults to
the value of DEBUG).
IMHO, having lots of includes is not a bad practice in itself. The alternative would be repeating the code, which violates the DRY principle.
If you find yourself including the same template multiple times within one template, you might want to consider a custom inclusion tag.
If you are really worried about performance, look into caching and specifically template fragment caching.
According to Django documentation:
using {% block %} is faster than using {% include %}
heavily-fragmented templates, assembled from many small pieces, can
affect performance
You can use extends and block
Few examples:
In base.html I use these blocks
...
{% block navbar %}
{% endblock %}
{% block sidebar %}
{% endblock %}
{% block searchbar %}
{% endblock %}
{% block content %}
{% endblock %}
{% block footer %}
{% endblock %}
...
Now I extend base.html into login.html. Say my login.html just need navbar, content, and footer
{% extends 'base.html' %}
<h1>Login </h1>
{% block navbar %}
This is my navbar
{% endblock %}
{% block content %}
Here is my login form
{% endblock %}
{% block footer %}
This is footer
{% endblock %}
Now I extend base.html into home.html. Say my home.html need navbar, sidebar, searchbar, content, and footer
{% extends 'base.html' %}
<h1>Home page </h1>
{% block navbar %}
This is my navbar
{% endblock %}
{% block sidebar %}
This is sidebar
{% endblock %}
{% block searchbar %}
{% endblock %}
{% block content %}
This is homepage contents. This will not render which you use in login.html **content** block
{% endblock %}
{% block footer %}
{% endblock %}

base.html contains {% extends 'base.html' %}?

I'm trying the django-cms tutorial,
There is something I don't understand at the end of this part :
I have to add a template at /mysite/templates/polls/base.html. But this file has to begin with {% extends 'base.html' %}.
Is that normal? Is the file this line refers to an other base.html file? The one in the parent directory perhaps? I'm not sure at all.
Thank you for your help.
Extending from a base.html like that would suggest, like I do, that you have a base.html file at the root template directory of your project to handle the core markup;
{% load cms_tags menu_tags sekizai_tags cache i18n %}
{% load static from staticfiles %}
<head>
<meta charset="utf-8">
{% block head %}{% endblock head %}
<title>
<script type="text/javascript"
src="{% static 'project/external/jquery-1.11.2.min.js' %}"></script>
{% render_block "css" %}
{% render_block "js" %}
{% block styles %}{% endblock styles %}
{% block scripts %}{% endblock scripts %}
</head>
<body>
{% cms_toolbar %}
{% block content %}
{% endblock content %}
{% block footer-scripts %}{% endblock footer-scripts %}
</body>
</html>
That way, when you setup templates in your apps you can start with a base.html for that app which may extend the base blocks for the head tag or elsewhere.
Usually I have a setup similar to myproj/templates and then app templates like myproj/project/templates and myproj/app1/templates. That first templates dir sits next to manage.py and I use the project dir to hold settings & any templates specific to that project like types of CMS page; article.html etc.
You don't have to extend base.html but if you don't, then you need to recreate all that markup again so by using this template model you'll be able to limit repeated markup.

How do I wrap some html around a block in a django template?

I have a base template (base.html) like this:
<doctype html> etc etc
{% block content %}{% endblock %}
It is used by many other templates in my site, but I have a third party app that comes with its own templates which inherit from tp.html which in turn inherits from base.html. These templates are mostly fine but I need their content blocks to be wrapped in a div. I could change the third party templates to use a sub_content block and modify tp.html like so:
{% extends "base.html" %}
{% block content %}
<div class="third-party-app">
{% block sub_content %}{% endblock %}
</div>
{% endbock %}
but I don't want to have to modify all the templates in the third party app.
What I want is something similar to {$smarty.block.child} found in Smarty templates, or a way to achive the same. Any ideas?
You can use block.super like so:
3rd party template:
{% block content %}
<h1>3rd Party Content</h1>
{% endblock %}
your template:
{% block content %}
<div class="wrapper">{{ block.super }}</div>
{% endblock content %}
In base.html, add pre_content and post_content blocks either side of {% block content %}, then in tp.html add your and tags to these blocks. Slightly inelegant, but it'll work and you won't have to modify all your templates.

Stand-alone front-end modules in Django

I'm trying to create stand-alone front-end module (HTML, CSS & JS) to integrate into a Django app.
The best example for what I mean is a "map" module, which I'd like to include in various, unrelated pages, possibly in different locations in each page.
I have a template that provides the HTML code that I need for the map, and I'd like the CSS and JS code to also be included through this template, to ease handling of front end dependencies.
Up until now, this can be achieved using the {% include %} tag.
But including stylesheets and scripts in the middle of the HTML page is an extremely bad practice when it comes to front-end performance. (CSS should be included in the <head>, JS should be included at the end of <body>)
My problem could have been solved if {% include %} tags would have been rendered as part of the template that included them and could have overridden {% block %} tags. That is not the case in Django. {% include %} tags are first rendered to HTML and only then included, so they cannot override {% block %} tags.
Looking around past questions around this subject suggest that the common wisdom is to use template inheritance (i.e. {% extends %}) instead of {% include %}, but since I'd like my modules to be independent, I don't see how I can use inheritance in my case.
What can I do to maintain my front-end dependencies inside the templates while maintaining front-end performance best practices?
Thanks!
To create your map template tag in the first place, use inclusion tags.
Concerning the problem with the static files, I'd create a related template tag that dumps the static file references into your current template. Then include that template tag in a block.
If your base template is in base.html and the page template is at page.html:
base.html
<html>
<head>
{% block css %}
<link rel="stylesheet...
{% endblock %}
</head>
<body>
{% block content %}{% endblock %}
{% block scripts %}{% endblock %}
</body>
</html>
page.html
{% extends 'base.html' %}
{% block css %}
{{ block.super }}
{% map_css %}
{% endblock %}
{% block scripts %}
{{ block.super }}
{% map_scripts %}
{% endblock %}
{% block content %}
content...
{% map_html %}
content...
{% endblock %}