Taking all javascript from html to page-specific js file - django

What bit bothers me about django, is that I see in many examples that raw javascript is included in html with <script> tag. I would like to have it in independent files which are included in every page in <head> tag so that html stays clean. So that I will call something like {% add_jscript %}some js code{% endaddjsscript %} anywhere in the template to add js code. After all processing when the page is generated and it will dynamically collects all portions of added js code from processed templates and serve it as one js file.
Some app already does this or am I forced to do this on my own ?

I use django-sekizai (https://github.com/ojii/django-sekizai/) for this kind of thing. If I understand you correctly, I believe that is what you are looking for.

I know I'm a bit late to the party, but another option you could try (shameless plug) is a django app i've been working on which will allow you to inject django variables directly into external javascript files, a la Require.js
django-js-variable-injector

Related

How could I not include all the css and js files in every page in rails 4.0?

I'm a newbie. Here's my problem. I just found that all css and js files generated by rails under app/assets are included in every page. I was considering how I could separate them into local ones(just for this page), and global ones(for all pages).
For example, I would like to put jquery.js in all my pages. But for 3DHelper.js, I hope it only appear in specific pages.
Are there any good ways to do this?
Assets pipeline gives you a good improvements in performance when you avoid using separate css/js files in your APP. And it is strongly recommended to follow this way!
If you would like some js file is executed only on some pages you can do the following:
add controller/action names to data or class attribute to body (in layout)
<body data-controller="<%= controller.controller_name %>" data-action="<%= controller.action_name %>">
add if condition to your js file which should be executed only on specific page. Something like this
if (($('body').data('controller') == 'YourSpecificController') && ($('body').data('action') == 'YourSpecificAction'))

Script Precompile Handlebars Templates in Script Tag

I have a fairly big webapp with lot of templates. I am looking to save time by precompilation of these files.
Currently, I use a script wrapper so that I can load it dynamically and package them in html
<script id="all-domain-users-model-template" type="text/html">
<td></td>
<td>{{domain}}</td>
<td>{{name}}</td>
<td>{{email}}</td>
<td>{{is_account_owner}}</td>
<td>{{#if is_account_owner}}Delete{{/if}}</td>
</script>
There are many many such files. One file can have more than one definition..
I am looking for ideas for a script to read the name in id, parse html, compile and put it back using id.templates in a js file.
I have seen Using pre-compiled templates with Handlebars.js (jQuery Mobile environment) - the accepted answers mentions that the script tag was removed before copying.. But in reality, its almost impossible..
I use grunt-ember-templates to precommpile my ember handlebars templates.
For a good example of this grunt plugin in use check out this example todos application.
It gives a good example of using grunt for your build process, testing, etc, and includes template precompilation.

What's the best way to DRY in Angular within Django?

I'm new to Angular, and to Django, and to DRY (Don't Repeat Yourself) so forgive me if this really simple and obvious... I've somehow missed it.
I have a dozen or so partials and a couple of them share a similar code block. I've learned how to use {% include 'template.html' %} to keep things DRY in django templates, however this doesn't work inside client side partials.
So I looked into ng-include with a <div ng-include="/groups/template.html"></div> and while that kind of works it changes the scope (which is over my head) so I cannot get my partials code to work on that included codeblock. But my biggest issue here is that the code block I'm including has to be via a routable URL in the urls.py file. This seems to go against security and usability.
Is what I'm asking for even possible? I'd love Angular to grab an external codeblock and drop it into the partials file server side when it puts the partials file into the cache.
Your Angular templates should be placed in your static folder like js files.
The structure can be like this one:
static/
js/
views/ #Put here your angular templates
Then, you can call ng-include like this:
<div ng-include="{{ STATIC_URL }}views/template.html"></div>

What are the pros and cons in serving CSS and JavaScript using Django template system

Often, I encounter scenarios where I see it makes sense to use template tags in CSS and JavaScript files, such as the use of {{ STATIC_URL }} in CSS to access image. I understand the only way to achieve this is to have CSS and JavaScript files served by Django. I am interested in this approach. But before I commit, I want to hear you experts' experience on it. What are the pros and cons of this approach? Thx.
Pros:
You can make a lot of per-request decisions about how things look and behave.
You can keep the number of different CSS/JS files to a minimum.
Cons:
Browsers tend to cache CSS and JS aggressively, so you'll need to use some aggressive anti-cache techniques. Of course, this means disabling caching for some/all static files.
Every CSS and JS request will consume another thread of your WSGI server. In a normal request/response cycle, each request generally takes up one thread; you're effectively tripling this, at least, so now your app that could handle 200 simultaneous requests now can only handle 66.
When your site makes it big, a CDN probably can't help you.
Alternatives:
Tweak the CSS via javascript, and set a javascript variable inside your page template to control the tweaks.
Use multiple CSS files and control their inclusion dynamically.
Generate static files as needed, but then cache them to disk and serve them via mod_xsendfile. This only works if you are serving static files from somewhere the django process can write to, such as on the same machine or a network mount.
Personally, I've been sticking with the Django team's advice to make CSS and JavaScript static files, served directly by the server instead of via Django. It hasn't been a problem and has simplified a lot of things. Generally, any time I think I need a dynamioc CSS or JS file, there's a way to refactor so I don't.
For example:
the use of {{ STATIC_URL }} in CSS to access image
I'm not sure how variable your {{ STATIC_URL }} is, but I've found that using the <base> tag in my pages fixes a lot of things. I assume this is for background images? Could you update your question to give an example?
Another thing I've done is, if my JavaScript needs dynamic data, I'll put most of the code in a JavaScript library I serve as a static file and then put the minimum dynamic stuff in a <script> tag at the end of the page. Usually I'll put it all in an object (looking a lot like JSON) and then just pass that object to a function. Come to think of it, you could just take all the dynamic stuff, make a dictionary out of it in your view function, encode it into JSON, and pass it via context. Then your page template just looks something like:
<html><head>
...
<script src="{{ STATIC_URL }}/js/foo.js"></script>
...
</head><body>
...
<script>
foo_main({{ foo_params_json|safe }});
</script>
</body></html>
This makes it a lot easier to reuse this code.

Best way to keep related files together in Django

What’s the best way to keep related files together in Django?
In addition to our HTML templates, most views have at least one additional JavaScript file, and possibly an additional CSS file. For example:
item_detail.html
item_detail.js
item_detail.css
We want to keep these files side-by-side if possible, so we don't have to look in two or three directories to find them.
Update: I do know that it’s dumb to defeat caching and that’s not what I’m asking. Each page loads several JavaScript and CSS items that are properly cached. For example:
<!-- at top of file -->
<link rel="stylesheet" href="/master/css/site-main.css">
<!-- at bottom of file -->
<script type="text/javascript" src="/master/js/jquery.js"></script>
<script type="text/javascript" src="/master/js/site-main.js"></script>
That part is fine.
In addition to this, each page loads page-specific JavaScript and CSS:
<link rel="stylesheet" href="/static/css/widgets/item_detail.css">
<script type="text/javascript" src="/static/js/widgets/item_detail.js"></script>
In this example, item_detail.js would have event handlers that are needed on the item detail page (only).
Unfortunately this means that I now have several parallel directory structures for this view:
my_site
widgets
item_detail.html ← This is the view
static
css
item_detail.css ← This is the view-specific CSS
js
item_detail.js ← This is the view-specific JavaScript
What I want is this:
my_site
widgets
item_detail.html ← This is the view
item_detail.css ← This is the view-specific CSS
item_detail.js ← This is the view-specific JavaScript
Due to the way views work in Django, it’s not clear to me that this is possible.
If you are just organizing stuff for development, you can symlink you template dir with all template, css and js files to directory you are serving static files too.
So from your example: add my_site/widgets to Django TEMPLATE_DIRS config and cp -s my_site/widgets to directory you have your static files in.
This is dirty hack and, please, don't use it in production as it is very insecure IMHO. But if you want to have neatly organized project in development stage - then I see this as one possible solution.
And also consider that this might give you loads of headache when you move from development to production as stuff WILL fail.
I agree with freiksenet. A solution to the problem he adresses could be aggregating the various css and js files. The whole site then uses just one css and one js file. The first load would be higher, yes, but a big part of the speed of a site is in downloading files, and if caching is done right, aggregation of these files helps imho.
I unfortunately don't have an answer to your main question.
I keep javascript in files separated by function and combine them into a single minified js file with a pre-commit hook (right after the tests run).
for example: I have several jquery-ui dialogs on the site I'm currently working on. Each dialog's functionality is broken off into it's own js file for maintainability. And all the needed js files are "included" on the development pages using a short base.js file like so:
function include(filename) {
document.write(unescape("%3Cscript src='" + filename + "' type='text/javascript'%3E%3C/script%3E"));
}
// include-js (external)
include('/site_media/jquery-plugin1.js');
include('/site_media/js-sources/dialog1.js');
my pre-commit hook does a regex on this file...
include\('/site_media/(.*)'\);
and feeds all the files into YUI compressor.
So I guess the answer to your question is... I put them wherever makes sense to me logically, because on the live site, it'll all be in the minified JS file(s) anyway
You don't want to have your templates available as static files -- they may contain sensitive information or details about the page's implementation which are not appropriate for the public to see.
CSS and JS do not have to be segregated into separate directories -- simply place them in the static/ directory.
my_site/
widgets/
item_detail.html
static/
item_detail.css
item_detail.js
One approach I’m testing:
my_site/
widgets/
item_detail.html
item_detail.css
item_detail.js
These are not shared statically. Instead, in the HTML template:
<script type="text/javascript" charset="utf-8">
{% include "widgets/item_detail.js" %}
</script>
(Similar code for CSS.) I would only do this for page-specific JavaScript and CSS, not site-wide stuff that can benefit from caching.
This dumps the actual JavaScript and/or CSS right into the template, yet allows me to keep them in separate files for development purposes. This is nice, development-wise but defeats some JavaScript and CSS caching, but only for page-level stuff that’s not re-used on any other page.