Why do I need to define both STATIC_URL and STATICFILES_DIRS? - django

If I define only one, the page displays without any CSS/JS. If I define both, the pages load fine. Why is that? I thought STATICFILES_DIRS is extraneous?
There's an answer here but it doesn't answer why I need both. It simply says what both does, which in my eyes is the same thing. What's the difference?
List of definitions for STATIC/STATIC_ROOT/STATICFILES_DIR

From what I have scoured on StackOverflow, I think I can sum it up as follows:
STATIC_ROOT is referenced as the static server, be it the default Django static server or the static server made on Heroku/etc. You point to this in urls.py
STATICFILES_DIR is referencing the stuff within static assets so if there are separate folders, one for CSS, one for JS, etc.
Feel free to add!

STATICFILES_DIRS is extraneous. You only need to use it if you are using a static files directory outside of the static files directories inside of your apps. Without seeing more of your code, and the structure of your project I can't even begin to guess why your pages aren't loading, but you definitely do not need to specify a STATICFILES_DIRS.

Related

Referencing Django's versioned static resources

When I run python manage.py collectstatic, it makes a copy of each image, JavaScript, and CSS file with a hash in the filename:
Post-processed 'css/theme.css' as 'css/theme.afeb1fc222a9.css'
Post-processed 'css/custom.css' as 'css/custom.585e1b29ff9a.css'
...
I'm assuming this is just a way of making a versioned filename for better caching; the client or CDN can be told to cache this file indefinitely, because if I make a change, the hash will differ, and I'll just reference the new version by the new name.
However, I'm not clear on how I'm supposed to reference this URL. The documentation on serving static files just says,
In your templates, either hardcode the url like /static/my_app/example.jpg or, preferably, use the static template tag to build the URL for the given relative path by using the configured STATICFILES_STORAGE storage (this makes it much easier when you want to switch to a content delivery network (CDN) for serving static files).
I went through my templates and dutifully switched every static resource (including the CSS files) from a hardcoded URL to a {% static "..." %} template tag, assuming it would map to the versioned filename where appropriate. But it doesn't.
I'm also using WhiteNoise for serving the resources, and I'm not entirely sure how it affects things, but it also says,
Want forever-cacheable files and compression support? Just add this to your settings.py: STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
But I have that in my settings file and it also doesn't seem to do anything with these versioned filenames.
If DEBUG is True then the static url will be 'css/theme.css' instead of
'css/theme.afeb1fc222a9.css'

How to collect Django static files with the same name?

Three of my Django apps have static files with the same name app1/static/css/mycss.css, app2/static/css/mycss.css, app3/static/css/mycss.css. How do I collect them all to STATIC_ROOT since default behavior of DJango is to collect only the first one encountered among the same named static file?
If you don't want the static files to be getting in each others way, give them their own name space by creating a suitable folder structure. Example
app1/static/css/app1/mycss.css
app2/static/css/app2/mycss.css
Alternatively if you want to combine all the CSS into one big CSS look into django-compressor

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.

Serving static files in development with django-devserver

I finally got around to trying out django-devserver. It's installed and working but static files refuse to load (Django 1.3). (Note: static files work fine with the standard runserver management command, before switching to django-devserver, so all the configuration settings are fine.) I came across this bit in the README:
DEVSERVER_IGNORED_PREFIXES = ['/media', '/uploads']
A list of prefixes
to surpress and skip process on. By default, ADMIN_MEDIA_PREFIX,
MEDIA_URL and STATIC_URL (for Django >= 1.3) will be ignored (assuming
MEDIA_URL and STATIC_URL is relative)
Which seems very odd because the whole point of using runserver is to not have to have an actual real web server setup, especially just to serve static files in development.
Oddly, though, even though it mentions ADMIN_MEDIA_PREFIX, I found that the admin actually loads all its static resources fine, which leads me to believe that maybe I'm just missing something somewhere.
Anyone ideas?
From the URL in #MarkLavin's comment, I actually came across (rather, reminded of) the following:
# Add to end of urls.py
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()
That will allow the static files to be served and is ignored in production, so there doesn't seem to be any side effects to the approach. However, it irks me a little to have to modify my urls.py just for this, but it's probably only temporary until the noted pull request is merged.
If anyone has any other solutions, feel free to add them, though.

django documentation, serving static files, 3 simple steps? Nope

https://docs.djangoproject.com/en/1.3/howto/static-files/
Trying to serve static files i was put on to the above link.
The link tells me when serving static files in development
Put your static files where they will be found, 'home/jamie/mysite/static/'
Done!
2.Make sure that django.contrib.staticfiles is included in your INSTALLED_APPS.
For local development, if you are using runserver...you’re done with the setup.
Done!
3.You’ll probably need to refer to these files in your templates. The easiest method is to use the included context processor which allows template code like:
<img src="{{ STATIC_URL }}images/hi.jpg" />
Done!
Wow, that seems too simple, surely it wouldn't work,
and sadly, no.
{{ STATIC_URL }} when i checked, equals None. Now STATIC_URL by default is none, therefore these instruction haven't done a thing. Surely i've done something wrong and the django documentation is right. But i cant figure out where in the three simple steps i've gone wrong.
Try setting STATIC_URL = '/static/' in your settings.py.