Best way to keep related files together in Django
-
18-09-2019 - |
Question
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 viewitem_detail.css
← This is the view-specific CSSitem_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.
Solution
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.
OTHER TIPS
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.