How to best manage Django templates & static content? - django

So, my team and I are new to Django development. We've been trying to design our project structure over the last couple weeks, and we've done a lot of reading to try and get a grasp of the best practice of doing this.
However, we are still struggling to get our heads around the best way to store our templates/static files that are generic to all applications.
Let me detail our structure we've implemented so far:
root-folder/
app-1/
static/
app-1/
css/
js/
img/
templates/
base.html
base-app-1.html **extends base.html
app-2/
static/
app-2/
css
js
img
templates/
base.html **extends base.html at 'project-name' level
base-app-2.html **extends base.html
project-name/
collectstatic/
templates/
base.html
static/
base/
css
js
img
The one thing that bugs me with this structure is that our top level templates reside inside the 'project-name' level. I would like to see this folder at the same level as our root level static folder.
However, I don't want to move the root level static folder content into 'project-name/collectstatic' because I don't want to have files inside that folder being version controlled.
We realise that there is no definitive answer to this problem in the Django world. But, are we on the right lines? Have we misunderstood something?
A couple ideas we've got are:
To have an app dedicated to top level templates and htdocs called something along the lines of 'general' or 'generic'.
To move the 'project-name/templates' dir to the root level along side our 'static' folder there.
To stop talking about this problem and go with the structure drawn out above.

In Django it's preferable to rely on staticfiles' AppDirectoriesFinder finder and the template's 'app_directories.Loader` loader classes for managing your static files and templates.
That means that you'll have some sort of project.core, project.base or project.commons application that you'll populate with base templates and static resources that are reused throughout your project.
I'm assuming your problem with the project-name/collectstatic/ folder is that it's your defined STATIC_ROOT, on a path that's under version control. Ideally, you'll move your static and media root outside of your project's sources. The simplest solution is to move it next to your project's top-level package, in the standard project layout for distributing Python packages, or to your Web server's preconfigured document root.
In either way, this should move your locally generated static resources outside of your project's Python packages.

Related

django: how to include a static file in a template?

In a Django project, I would like to include a static file in a template. The following is the the project structure:
proj/
main/
static/
main/
js/
main.js
news/
templates/
news/
news.html
In news.html, I would like to include the main.js with the following hypothetical format:
{% load staticfiles %}
...
{% include {% static 'main/js/main.js' %} %}
How do I do it?
The include directive only searches file in template directories. What you could do (although I wouldn't) is to change your settings to also include the static files:
TEMPLATE_DIRS = [
...
"path/to/your/statics",
]
I have a couple of ideas.
The easiest thing to do would be to ensure you have the filesystem loader enabled, and you include the relevant directory containing static files in TEMPLATES[0]['DIRS'] (previously TEMPLATE_DIRS). The caveats are that it will not pick up static files contained inside your installed applications automatically, unless you list them in DIRS, too. Another option would be to use STATIC_ROOT, but that will only work if you run collectstatic every time you change the static file, which you normally don't have to do in development. Another pitfall is that it will only work with local static storage, not if you use any CDN or otherwise host your static files on a different host / network / whatever.
The other thing you can do is to write your own template loader which will use the static files API to load statics as templates. This is a bit more involved, but it should be able to access static files regardless of how they are stored and served.
Should you choose either option, you still have to be careful. For instance, you'll have to ensure that the static files you're including as templates are safe to include into HTML or whatever other context you're using them in. There will be no escaping going on.
In case you're trying to optimize the number of requests the client has to make, there are better ways. You're most likely better off implementing some pipeline that will pre-process and minify your static files. Including any significant chunk of CSS / JS into the HTML will make it impossible for clients to take advantage of caching, forcing them to re-download the same static content over and over again, likely impacting the performance negatively.
Edit: Since you want to just include some dynamic JavaScript variables, that's not a static file at all. What you really want is to create a template containing JavaScript code, and not mess with handling static files as templates. There is no rule that would say every javascript needs to be a static file. If it's dynamic, it's not a static file.
For the record, this was a typical instance of the XY problem. Problem X was dynamically assigning values to JavaScript variables when rendering templates. You came up with including static files in templates as a potential solution, but then got stuck with problem Y, which was that you didn't know how to include static files in templates.

How to create directory structure

I am not quite sure if my directory structure has the correct hierarchy and I decided to stop the development unless I will have it good.
I have order, customers, users .
So what I have is:
myproj
|-myproj
|-web_app
|---orders (with views.py, ajax.py)
|----templatetags
|---users
|---customers
|---search
|---static
|-----app
|-------_base
|---------css
|---------images
|---------js
|-------orders
|---------css
|---------images
|---------js
|-------customers
|---------css
|---------images
|---------js
|-------users
|---------css
|---------images
|---------js
|-----bootbox
|-----bootstrap
|-------css
|-------fonts
|-------js
|-----dajax
|---templates
models.py is in web_app directory, there are models common for all modules. My questions are:
1) What changes would you do in this structure? (static files for every module should be where?)
2) I have problem of inserting custom template tag defined in orders/templatetags/orders_extras.py from users template. How can I make some common templatetags for every "module" ?
Thank you.
This is explained in Django documentation very well. The good approach is:
Project
- App1
(Put app specfic templates to the app templates/App1/templates/App1/template files
- App2
- App3
- template for project (templates/ files)
Now, if you want template tags only for specific app create /templatetag directory under that app and do that.
For universal template tag do this:
Project
- templatetags
- __init__.py (Make sure it contains __init__.py)
- polltag.py
Explained here: https://docs.djangoproject.com/en/dev/howto/custom-template-tags/
How can I make some common templatetags for every "module" ?
You should place it near the templates directory
myproj
|-myproj
|-web_app
|---templates
|---templatetags
|---orders (with views.py, ajax.py)
|----static
|-----static_files_here
dajax
Is this about dajax? If you are new to django, I recommend to get away from this stuff. You can just watch the issues list of this project to decide whether you should use it or not. The problem not only about that dajax is bad or good, but that these issues are being made by newbies that don't understand how ajax works, what are csrf tokens and so on.
When I started to learn django, I tried dajax too, but finally I have realized that you should understand how ajax and django works by their own and then try to combine them.

where to place the js_plugins and css_plugins?

where to place the js_plugins and css_plugins?
I want to create a html/css template.some css files and are coded myself,such as
css/my.css
js/site.js
but sometimes I want to use some existed css or js plugins from other people who had shared on web,such as
1.some plugins only have css,no js needed. (ex:css3_button.css)
2.some plugins have both css and js. (ex:jquery.prettyphoto.js && jquery.prettyphoto.css)
for these plugins ,where should i put them in my template folder?
i do it like this bellow, but i don't think my structure is good enough.
index.html
css
....my.css
js
....my.js
css_plugin
....css3_button
........css3_button.css
js_plugin
....jquery_prettyphoto
........jquery.prettyphoto.css
........jquery.prettyphoto.js
how to place these files, to ensure the easy managing in the feature?
I use static folder, which includes folders for CSS, images and JavaScript. You can also add a folder for your plugins, where each plugin will be in its own folder.
You can replicate your general structure inside each plugin folder, but most plugins come pre-organized, and changing their structure is not always easy.
example
index.html
static
...js
...css
...img
...plugins
......myFavoritePlugin
.........css
.........js
.........img
......myFavoritePlugin2
.........css
.........js
.........img
Keeping the plugin files together makes their maintenance easier, but it affects performance. It is best practice to combine CSS and JavaScript files when deploying on production machines. You can have best of both worlds if you use build scripts, such as ant

Django: What's the best practice on structuring global templatetags?

I realize that templatetags are mainly used specific to applications which are INSTALLED_APPS, such as articles/templatetags/, but in my case I need tags for generic things such as navigation which doesn't have an application.
I'm currently keeping templatetags in my project dir. and in order for it to get picked up I added my project to INSTALLED_APPS - this works but I'm not sure if this was the right thing to do - are there any downsides?
I would do it the same way Django provides its additional template tags, i.e. creating an own package/application( django.contrib.humanize, django.contrib.markup, django.contrib.webdesign)
These are just three "normal" packages, that have a templatetags package inside. The name of the module inside tempaltetags is the same as the package/application name (e.g. humanize.py).
Then put it somewhere where Python can find it.
You could also create some kind of "meta" package templatetags and put everything there, e.g.
templatetags
- navigation
- __init__.py
- templatetags
- _init__.py
- navigation.py
- other
- ...
Of course you have to add those to you INSTALLED_APPS (e.g. templatetags.navigation) and load them in your template (e.g. {% load navigation %}).

How to make project templates and Satchmo templates co-exist?

I'm working with a Satchmo installation that resides within an existing project. This project has its own templates as well as templates for some of the various apps that are installed. Some of these app-specific templates have their own app_base.html variations that expect to derive form base.html. I'd like to be able to do the same thing with my Satchmo templates and have them reside within my project's base, but also have some additional html added around all of them.
/templates
base.html
index.html
/news
news_base.html (extends base.html and adds news-specific template features)
index.html
detail.html
/store
base.html (overriding Satchmo's base)
This structure works somewhat, but not how I expected. in /store/base.html (Satchmo's base) I've simply replaced everything with a test message. I can see the message, so I know satchmo is loading its base and not the site's base. However, I can't extend my project's base anymore since using:
{% extends "base.html %}
Yields a recursion error since its calling itself and the following simply won't work.
{% extends "../base.html" %}
I realize that I can change my project's base.html to a slightly different name and point all app-specific templates at them, but it seems like a pretty major hack on such a fundamental aspect of the template structure.
Hmm, I didn't think django looked up templates relatively like that.
Kinda crazy hack, but this should work:
/templates/store/base.html extends "global_base.html"
/templates/global_base.html extends "base.html"
Depending on how you have your template structure set up, it might also be a good idea to play with the settings.TEMPLATE_LOADERS variable.
TEMPLATE_LOADERS Default:
('django.template.loaders.filesystem.load_template_source',
'django.template.loaders.app_directories.load_template_source')
A tuple of callables (as strings) that
know how to import templates from
various sources. See The Django
template language: For Python
programmers.
For more information on how this affects the template loading process:
http://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types
From the way you describe your problem, it seems like by commenting out the "app_directories.load_template_source" file line, you might be able to better find a way to accomplish what you're doing.
django.template.loaders.app_directories.load_template_source
Loads templates from Django apps on
the filesystem. For each app in
INSTALLED_APPS, the loader looks for a
templates subdirectory. If the
directory exists, Django looks for
templates in there.
This means you can store templates
with your individual apps. This also
makes it easy to distribute Django
apps with default templates.
For example, for this setting:
INSTALLED_APPS = ('myproject.polls',
'myproject.music') ...then
get_template('foo.html') will look for
templates in these directories, in
this order:
/path/to/myproject/polls/templates/foo.html
/path/to/myproject/music/templates/foo.html
Note that the loader performs an
optimization when it is first
imported: It caches a list of which
INSTALLED_APPS packages have a
templates subdirectory.
This loader is enabled by default.
I just had this same problem. It looks like the satchmo developers planned for this by putting an "empty" base in the shop template directory. While this may not be relevant to you anymore, I would have like to have seen this here.
You can make a "shop" directory in your template directory and copy the main satchmo base.html to that directory.
This worked for me.