I'm trying to show images/js/css in my Django templates with {{ STATIC_URL }} label. In theory, this works because in browser, when i see the printed code the path to requested file is something like "/static/images/blabla.jpg". But the file is not showed, so i guess the problem is in Django project.
My settings looks like this:
STATIC_ROOT = '/absolute/path/to/static'
STATIC_URL = '/static/'
STATICFILES_DIRS = (
# Put strings here, like "/home/html/static" or "C:/www/django/static".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
'/absolute/path/to/static'
)
In my urls.py:
url(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
But i don't know why all files in static directory are not displayed in templates.
Any tip or advice?
Thanks mates.
First, it looks like there is a mistake in your settings. You should understand the django.contrib.staticfiles collectstatic command:
Collects the static files into STATIC_ROOT.
[...]
Files are searched by using the enabled finders. The default is to look in all locations defined in STATICFILES_DIRS and in the 'static' directory of apps specified by the INSTALLED_APPS setting.
So, it seems like a mistake that STATICFILES_DIRS contains STATIC_ROOT, since the contents of STATICFILES_DIR is ment to be copied into STATIC_ROOT by collectstatic.
The url is not necessary. You should either:
use runserver with DEBUG=True, in that case django will serve static files by default, in doubt use staticfiles_urlpatterns or
use a real httpd to serve STATIC_ROOT on STATIC_URL, in that case you should generate STATIC_ROOT from STATICFILES_DIRS (and actually each app's 'static' subdir, which is the point) with the command collectstatic
When in doubt, the findstatic command may also prove useful.
django.contrib.staticfiles might look a little confusing at first, but when you understand it fully you love it <3
Related
I am trying to start Django on Heroku. I looked around Stack Overflow, I tried different things, but I cannot figure it out. It looks similar to all the questions related to staticfiles problem on Django, unfortunately I don't know where the problem is. My project runs just fine with DEBUG = True, but when I change it to False, I get following traceback:
2020-11-09T13:13:42.801384+00:00 app[web.1]: Missing staticfiles manifest entry for 'order/css/open-iconic-bootstrap.min.css'
It happens on all of my apps that require staticfiles. I tried to find manifest.json, but it does not exist. So I think this is the issue.
Here are my relevant settings:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
#more ...
]
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedStaticFilesStorage'
django_heroku.settings(locals())
Thanks for looking into this!
#keome in the comments already gave you the first steps in debugging this issue so I won't repeat that here.
Notwithstanding the issues they raised (which should be looked at first), I think the key issue is that your whitenoise configuration isn't set up to generate a manifest. You probably want:
# Serve compressed and manifested static files
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
The reason your current configuration would work with DEBUG=1 is that in debug mode, django will fall back to serve static files itself (neither secure nor efficient).
Second, make sure that you run collectstatic with the same storage configuration as you're running the server - I cant see what settings files you have, but it seems like you've collected static without a manifesting strategy, but you're trying to serve it with a manifesting strategy (and hence django is confused by why there isn't a manifest).
Incidentally, whitenoise by default creates a staticfiles.json file, not a manifest.json file, and it's served as a static file. So if your STATIC_URL = "/static/" then you can find the manifest at <your-domain>/static/staticfiles.json.
Edit - clarification
The reason the manifest of staticfiles isn't actually called manifest.json is because that'd conflict with the usual name of the manifest.json served as part of a Progressive Web App (spec here), which is kind of similar (in that it can serve as an instruction to the browser of where to find certain files) but not the same.
I'm having trouble understanding how static files are handled in Django. I've read through the official Django documentation as well as multiple threads, including this wonderful one here:
Differences between STATICFILES_DIR, STATIC_ROOT and MEDIA_ROOT
Most people define the STATICFILES_DIRS list as a list of paths where django will search for additional static files aside from the app's static folder.
I understand that, but what does this have to do with the formfields I'm overriding in my admin.py?
I have overridden the default ManyToMany form to the FilteredSelectMultiple widget in a few of my admin models like so:
from django.contrib.admin.widgets import FilteredSelectMultiple
formfield_overrides = {
models.ManyToManyField: {'widget': FilteredSelectMultiple("User Names", is_stacked=False)}
}
This works fine and produces the widget override I wanted: Functional Widget Screenshot
However, when I define STATICFILES_DIRS in settings.py to include my root static folder like so:
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static/'),
)
It breaks my override and defaults back to the original ManyToMany field form:
Broken Widget Screenshot
We do not have STATIC_ROOT defined in our settings.py as we don't plan on using the collect static feature. We plan on keeping/referencing our static files at the root static folder. Also in our settings.py we have:
STATIC_URL = '/static/'
I don't understand how these settings for dealing with static files are interfering with the formfield_override above. I would appreciate some insight on this, so that I could find a way to approach this issue.
Thank you!
I figured out the cause of my issue. I missed this portion in the Django documentation that explains STATICFILES_FINDERS: STATICFILES_STORAGE Documentation
It turns out that my production server was finding the static files in my outer root folder first, which were not up to date. This explains why I wasn't seeing my changes. I'm going to reconfigure the way I handle static files to ensure that the outer root static folder that my production server looks always has the latest static files via the collectstatic feature
I'm in the process of setting up my views in Django, but I'm confused about how to link it to my pageOne.html page so it shows that instead of the "Welcome" page. Currently, when I run the server using python manage.py runserver 127.0.0.2:8001 I get an error message that says "Template Does Not Exist at" pageOne.html.
I've set
TEMPLATE_DIRS = (os.path.join(os.path.dirname(BASE_DIR), "static", "templates"))
I've also tried
TEMPLATE_DIRS = ('/Users/andrewnguyen/Desktop/Websites/gale/python/techExercise/templates',)
but that hasn't really worked either.
Update:
Here's a screenshot. I imagine that my error is somewhere in my urls, settings or views.py. I've changed the path to my TEMPLATE_DIRS as mentioned in the comment below. That did not work. I've included an image of my file structure on Imgur: http://imgur.com/kR1xcGJ
Your TEMPLATE_DIRS settings should look like this:
TEMPLATE_DIRS = (
os.path.join(BASE_DIR, "templates"),
)
Update
After looking at that screenshot you posted, I can say you've made a lot of mistakes.
The templates folder is inside the static folder.
Move the templates folder out of the static folder.
There's a mistake in the return statement of your view.
It should look like this:
return render(request, 'pageOne.html')
There's no need to prepend /static/templates/ to the template name. Django automatically looks for templates in your settings' TEMPLATE_DIRS path.
And finally, nothing you're doing is very difficult. All these mistakes are caused by ignorance, since everything is mentioned elaborately in the docs. Please read them carefully.
I'm attempting to setup appropriate STATIC_URL and STATIC_ROOT values for a new Django project, and I'm running into a problem with using an absolute URL for STATIC_URL.
My project is structured like:
<project root>
static
media
src
<apps>
static
js
css
custom.css
i
settings.py
In my settings.py, I have
STATIC_ROOT = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../static/'))
If I set STATIC_URL = '/static/', then I can access http://localhost:8000/static/css/custom.css perfectly.
However, if I use an absolute URL like STATIC_URL = 'http://localhost:8000/static/', as though I were using a CDN, then http://localhost:8000/static/css/custom.css returns a 404 error.
Shouldn't these settings be effectively identical? The docs state STATIC_URL can be absolute. Why does the later setting fail to load static media?
I just tested the same thing, using http://localhost:8000/static/ doesn't work for me either.
In my settings I keep a development variable, so on localhost the url is '/static/' and when I'm deployed (and I set DEVELOPMENT = False), its a full url.
if DEVELOPMENT == True:
STATIC_URL = '/static/'
else:
STATIC_URL = 'https://www.mywebsite.com/static/'
I assume that you are using the static function from the django.conf.urls.static to serve your static files in the development environment (that means DEBUG=True). Now as you can read in the documentation this function is not working with the absolute urls with DEBUG enabled.
So from the docs:
https://docs.djangoproject.com/en/dev/howto/static-files/#serving-static-files-during-development
"This helper function works only in debug mode and only if the given prefix is local (e.g. /static/) and not a URL (e.g. http://static.example.com/)."
The cause and solution was simple, but discovering it was unintuitive based on how I described the problem. I failed to mention that my absolute STATIC_URL actually had a different domain (http://localmedia:8000/static/ not http://localhost:8000/static/).
I was doing this as part of a hack to simplify media hosting among several external development Windows machines I was using to test various versions of IE.
However, when there's a mismatch between the domain in STATIC_URL and runserver's local domain, Django only serves content from STATIC_ROOT and doesn't attempt to retrieve media from app folders. Not sure why, but that's the way it is.
If I ran manage.py collectstatic, it would effectively fix the 404 error by copying all app folder media into my STATIC_ROOT. Alternatively, I could just use the same domain in my STATIC_URL, and Django would automatically find any uncollected media in the app folders.
I'm trying my first proper webdev project and i'm learning the django framework.
I came here to ask about the cleanest way to use "static files", like the external CSS i'm referring to in one of my html templates. I tried reading through the official documentation on the subject but found it a little bit confusing as a beginner, i then tried googling but i noticed that most of the guides or stackoverflow answers differed slightly and i realised i needed a better understanding. Bit cheeky to ask but, could someone explain and summarise the process to me?
For reference, here is my project folder hierarchy. At the moment i'm trying to get the template base.html to use the sylesheet at CSS/base.css:
Also one of the things that keeps throwing me off is the use of absolute filepaths. So far i've managed to get away with just using relative filepaths, which makes more sense to me as the aim is to develop on the django test server then transfer it all onto my own server when i have one. (note: perhaps it's because i have no idea how complicated that transfer process is that i don't understand why absolute filepaths are prefered). What's the issue with using relative filepaths?
I realise that this has sort of become two questions, which is against the rules, but i really think both could be answered together and if i understood one it would probably aid my understanding of the other. Any help would be much appreciated.
Here is a set of code snippets from settings.py i have changed for including static files
import os
import django
DJANGO_ROOT = os.path.dirname(os.path.realpath(django.__file__))
SITE_ROOT = os.path.dirname(os.path.realpath(__file__))
Dynamically setting variables for SITE_ROOT directory
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(SITE_ROOT,'data.db'),
where the sqlite3 database is stored it needs absolute address
'USER': '',
'PASSWORD': '',
'HOST': '',
'PORT': '',
}
}
STATIC_ROOT = SITE_ROOT
STATIC_URL = '/static/'
store static files here
STATICFILES_DIRS = (
os.path.join(SITE_ROOT,'static'),
)
where the templates are stored
TEMPLATE_DIRS = (
os.path.join(SITE_ROOT,'templates'),
)
Now in templates use
{% load static %} --at beginning
<link href="{% static "css/bootstrap.min.css"%}" rel="stylesheet" media="screen">
this is an example showing how to access "css/bootstrap.min.css" in static directory
I'm going to assume you're using Django 1.3 or higher as that allows you to use staticfiles (docs) for static files. Here's the basic idea: each Django website consists of multiple apps (directories) that contain all the files needed for a particular part of the website (i.e., a models.py, views.py, a templates directory and also a static directory). This static directory contains the JavaScript and CSS files (as well as other static files for that app.
When deploying the website, you run the collectstatic command to gather all the static files into one directory. From that directory you then serve the static files to visitors of your site (i.e, Apache or a different web server can do that for you).
So the general structure of your web project could be:
manage.py
website/models.py
website/views.py
website/static/website/css/base.css
website/static/website/js/base.js
website/templates/website/base.html
static
settings.py
urls.py
You'll notice that the name of the Django app is repeated in the subdirectories of the static and templates directories. This is necessary because it keeps the files apart when they are moved to a general static directory. In the above example, the STATIC_ROOT is the top-level static directory and into this directory all your static files will be copied.
It's definitely worth reading the documentation of staticfiles as this project layout allows you to reuse Django apps in other projects with ease. For example, you can imagine a website that looks like this:
blog/models.py
blog/templates/blog/overview.html
blog/templates/blog/post.html
blog/urls.py
blog/views.py
photos/models.py
photos/templates/photos/overview.html
photos/templates/photos/photo.html
photos/urls.py
photos/views.py
manage.py
static
settings.py
urls.py
The apps blog and photos can now easily be reused in other websites if desired.
Really appreciate the time put into the #Simeon Visser's answer, and there was some really useful information there but it wasn't entirely what I was looking for. So I asked around and have sinister_user_name from reddit to thank for this, which I thought might help someone else:
Static files have changed a fair bit in recent releases so old blogs might be a bit of a mess.
I'll give it a shot:
In your templates you can use the static_url tag and django will fill in the path for you.
<link rel="stylesheet" href="{{ STATIC_URL }}css/bootstrap.min.css">
It fills in the static url by looking at your settings file. STATIC_URL defaults to /static/ I think in settings? If static files end up in a weird url on your corporate web server you can just change it in settings anyway and it will reflect in all templates. So it doesn't matter if they are absolute.
When you go to deploy you fill in STATIC_ROOT in your settings, this is just the path that you've set your webserver to find the static files. Then if you run manage.py collectstatic and it will copy them to that directory. That's the only function of STATIC_ROOT I think.
I keep the template directory separate from my static directory, mainly because you want your webserver just to serve static files, while templates are processed by python. So, static files are almost not part of your application as far as the web server views them. I keep my templates and static files in separate paths just in the base directory, mainly because both are not python source files.
So my project structure would be like:
manage.py
website/settings.py
app/models.py
app/views.py
templates/base.html
static/js/jquery.js
static/css/bootstrap.css
The problem with relative paths is that they will need to change if your url scheme changes.
Optional: I found in this blog which helps to not put absolute file system paths into the settings.py which is good if your working from multiple machines eg work and home :(
With the slightly different layout for 1.4 I use this at the top of my settings:
import os
import django
import manage
DJANGO_ROOT = os.path.dirname(os.path.realpath(django.__file__))
SITE_ROOT = os.path.dirname(os.path.realpath(manage.__file__))
instead of what they suggest (the location of settings has moved in 1.4 or 1.3) so SITE_ROOT is messed up. I think that might work.
Further on down in the settings I use this:
# Additional locations of static files
STATICFILES_DIRS = (
os.path.join(SITE_ROOT, 'static'),
)
This will tell the development server where to find the static files. You can do the same for templates or just use the full file path.