why django app not load static files when debug false? [duplicate] - python

Am building an app using Django as my workhorse. All has been well so far - specified db settings, configured static directories, urls, views etc. But trouble started sneaking in the moment I wanted to render my own beautiful and custom 404.html and 500.html pages.
I read the docs on custom error handling, and set necessary configurations in UrlsConf, created corresponding views and added the 404.html and the 500.html to my app's template directory (specified in the settings.py too).
But the docs say you can actually view custom error views until Debug is Off, so I did turn it off to test my stuff, and that's when stuff goes berserk!
Not only do I fail to view the custom 404.html (actually, it loads, but because my error pages each contain a graphic error message -as some nice image), the source of the error page loads, but nothing else loads! Not even linked CSS or Javascript!
Generally, once I set DEBUG = False, all views will load, but any linked content (CSS, Javascript, Images, etc) wont load! What's happening? Is there something am missing, concerning static files and the DEBUG setting?

If you still need to server static locally (e.g. for testing without debug) you can run devserver in insecure mode:
manage.py runserver --insecure

With debug turned off Django won't handle static files for you any more - your production web server (Apache or something) should take care of that.

In urls.py I added this line:
from django.views.static import serve
add those two urls in urlpatterns:
url(r'^media/(?P<path>.*)$', serve,{'document_root': settings.MEDIA_ROOT}),
url(r'^static/(?P<path>.*)$', serve,{'document_root': settings.STATIC_ROOT}),
and both static and media files were accesible when DEBUG=FALSE.

You can use WhiteNoise to serve static files in production.
Install:
pip install WhiteNoise==2.0.6
And change your wsgi.py file to this:
from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise
application = get_wsgi_application()
application = DjangoWhiteNoise(application)
And you're good to go!
Credit to Handlebar Creative Blog.
BUT, it's really not recommended serving static files this way in production. Your production web server(like nginx) should take care of that.

Johnny's answer is great, but still didn't work for me just by adding those lines described there. Based on that answer, the steps that actually worked for me where:
Install WhiteNoise as described:
pip install WhiteNoise
Create the STATIC_ROOT variable and add WhiteNoise to your MIDDLEWARE variable in settings.py:
#settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', #add whitenoise
'django.contrib.sessions.middleware.SessionMiddleware',
...
]
#...
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') ##specify static root
Then, modify your wsgi.py file as explained in Johnny's answer:
#wsgi.py
from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise
application = get_wsgi_application()
application = DjangoWhiteNoise(application)
After that, deploy your changes to your server (with git or whatever you use).
Finally, run the collectstatic option from your manage.py on your server. This will copy all files from your static folders into the STATIC_ROOT directory we specified before:
$ python manage.py collectstatic
You will now see a new folder named staticfiles that contains such elements.
After following these steps you can now run your server and will be able to see your static files while in Production mode.
Update: In case you had version < 4 the changelog indicates that it's no longer necessary to declare the WSGI_APPLICATION = 'projectName.wsgi.application' on your settings.py file.

If you are using the static serve view in development, you have to have DEBUG = True :
Warning
This will only work if DEBUG is True.
That's because this view is grossly
inefficient and probably insecure.
This is only intended for local
development, and should never be used
in production.
Docs: serving static files in developent
Updated link, and this
EDIT: You could add some urls just to test your 404 and 500 templates, just use the generic view direct_to_template in your urls.
from django.views.generic.simple import direct_to_template
urlpatterns = patterns('',
('^404testing/$', direct_to_template, {'template': '404.html'})
)

You actually can serve static files in a production Django app, securely and without DEBUG=True.
Rather than using Django itself, use dj_static in your WSGI file (github):
requirements.txt:
...
dj-static==0.0.6
YOURAPP/settings.py:
...
STATIC_ROOT = 'staticdir'
STATIC_URL = '/staticpath/'
YOURAPP/wsgi.py:
...
from django.core.wsgi import get_wsgi_application
from dj_static import Cling
application = Cling(get_wsgi_application())

You can debug this in many different ways. Here's my approach.
localsettings.py:
DEBUG = False
DEBUG404 = True
urls.py:
from django.conf import settings
import os
if settings.DEBUG404:
urlpatterns += patterns('',
(r'^static/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': os.path.join(os.path.dirname(__file__), 'static')} ),
)
Be sure to read the docs ;)
https://docs.djangoproject.com/en/2.0/howto/static-files/#limiting-use-to-debug-true

Ultimate solution:-
So basically when you make debug = False, Django doesn't want to take care of your static files.
So we want something that can take care of our files.
The answer is whitenoise.
pip install whitenoise in your environment
Add 'whitenoise.middleware.WhiteNoiseMiddleware' in your middleware list in settings.py.
This should be added just below the 'django.middleware.security.SecurityMiddleware' and above all the remaining middleware. So that your middleware list will look like this:-
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
# add it exactlyhere
'django.contrib.sessions.middleware.SessionMiddleware',
'...'
]
Add 'whitenoise.runserver_nostatic' on top of your installed apps
So that your installed apps list will look like this:-
INSTALLED_APPS = [
'whitenoise.runserver_nostatic',
'django.contrib.admin',
'django.contrib.auth',
'...'
]
Done, you will be able to serve static files in production now!!

From here I took help by mixing a few answers. Here, I am adding my whole parts. [I am doing this for a beginners help and for my future use as well]
Well at first the question is why Debug=False needed!
I put my project in AWS and it was being connection timeout after few hours because of memory leaking.
At first I thought for celery. [of course I am just a beginner]
Then I put DEBUG=False from DEBUG=True As we can see the security warning in settings.py
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
Once I did that my staticfiles were not loading successfully in webpages.
Then I searched everywhere and at first tried from here the --insecure command to runserver.
python manage.py runserver --insecure
Which is successful but I don't want the insecure mode in my project when it is in production.
And as the proper solution [according to me] I followed the steps below.
At first, I correct the static URL,root, and dir in settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
Then collect the static files by command
python manage.py collectstatic
Now the second step, [which also provided here]
At first install whitenoise in your project directory in the command line
pip install whitenoise
Then Add 'whitenoise.middleware.WhiteNoiseMiddleware' in your middleware list in settings.py.
This should be added just below the 'django.middleware.security.SecurityMiddleware' and above all the remaining middleware. So that your middleware list will look like this:-
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', #after this line
'whitenoise.middleware.WhiteNoiseMiddleware', #add it exactlyhere
'django.contrib.sessions.middleware.SessionMiddleware', #before this
'...'
]
Add 'whitenoise.runserver_nostatic' on top of your installed apps So that your installed apps list will look like this:-
INSTALLED_APPS = [
'whitenoise.runserver_nostatic',
'django.contrib.admin',
'django.contrib.auth',
'...'
]
Done, you will be able to serve static files in production now!! [I did on my local environment as well]
Just use the runserver command as always no insecure or anything needed.
python manage.py runserver
Boom!!! It's working for me.
Hahaha. I know kinda childish nature but I am so happy now.
Thanks to everyone who provided answers here and help my work.

This is Exactly you must type on terminal to run your project without DEBUG = TRUE
and then you see all assets (static) file is loading correctly On local server .
python manage.py runserver --insecure
--insecure : it means you can run server without security mode

For last versions of Django please look at the answer here: https://stackoverflow.com/a/7639983/6180987
For django version below 1.10 the solution should work:
Just open your project urls.py, then find this if statement.
if settings.DEBUG:
urlpatterns += patterns(
'django.views.static',
(r'^media/(?P<path>.*)','serve',{'document_root': settings.MEDIA_ROOT}), )
You can change settings.DEBUG on True and it will work always. But if your project is a something serious then you should to think about other solutions mentioned above.
if True:
urlpatterns += patterns(
'django.views.static',
(r'^media/(?P<path>.*)','serve',{'document_root': settings.MEDIA_ROOT}), )
In django 1.10 you can write so:
urlpatterns += [ url(r'^media/(?P<path>.*)$', serve, { 'document_root': settings.MEDIA_ROOT, }), url(r'^static/(?P<path>.*)$', serve, { 'document_root': settings.STATIC_ROOT }), ]

when i make DEBUG = True my static are doesn't work.
if i run my project in python manage.py runserver --insecure . By this i got my static as well.
Solution 1:
python manage.py runserver --insecure
Solution 2:
But I Need Permanent Solution. then i install pip install dj-static==0.0.6 and add some code to my wsgi.py file:
from django.core.wsgi import get_wsgi_application
from dj_static import Cling
application = Cling(get_wsgi_application())
and then i added some in setting.py:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, '/static/')
STATICFILES_DIRS = [
BASE_DIR / "static",
]

I agree with Marek Sapkota answer; But you can still use django URFConf to reallocate the url, if static file is requested.
Step 1: Define a STATIC_ROOT path in settings.py
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
Step 2: Then collect the static files
$ python manage.py collectstatic
Step 3: Now define your URLConf that if static is in the beginning of url, access files from the static folder staticfiles. NOTE: This is your project's urls.py file:
from django.urls import re_path
from django.views.static import serve
urlpattern += [
re_path(r'^static/(?:.*)$', serve, {'document_root': settings.STATIC_ROOT, })
]

I got this problem today and this fixed it while on development, If you still need to server static locally (e.g. for testing without debug) you can run devserver in insecure mode:
manage.py runserver --insecure
Don't worry because when in production, this hosting platform (Apache, Heroku E.T.C ) would handle serving the static files for you.
Note: Heroku Doesn't server static files, you'd want to put it on AWS or MS Azure

nginx,settings and url configs
If you're on linux this may help.
nginx file
your_machn:/#vim etc/nginx/sites-available/nginxfile
server {
server_name xyz.com;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /var/www/your_prj;
}
location /media/ {
root /var/www/your_prj;
}
...........
......
}
urls.py
.........
.....
urlpatterns = [
path('admin/', admin.site.urls),
path('test/', test_viewset.TestServer_View.as_view()),
path('api/private/', include(router_admin.urls)),
path('api/public/', include(router_public.urls)),
]
if settings.DEBUG:
import debug_toolbar
urlpatterns += static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
settings.py
.....
........
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
.....
....
Ensure to run:
(venv)yourPrj$ ./manage.py collectstatic
yourSys# systemctrl daemon-reload

This is normal and intended behavior.
Warning
This will only work if DEBUG is True.
you can actually view custom error views until Debug is Off
If Django is just reading from the filesystem and sending out a file, then it has no advantage over a normal web server, all web servers are capable to server the files on it's own.
Furthermore, if you serve static files with Django, you will keep the Python process busy for the duration of the request and it will be unable to serve the dynamic requests to which it is more suited.
For these reasons, the Django static view is designed only for use during development and will not work if your DEBUG setting is False.
Since during development we only usually have one person accessing the site at a time (the
developer), Django is fine to serve static files.

Support for string view arguments to url() is deprecated and will be removed in Django 1.10
My solution is just small correction to Conrado solution above.
from django.conf import settings
import os
from django.views.static import serve as staticserve
if settings.DEBUG404:
urlpatterns += patterns('',
(r'^static/(?P<path>.*)$', staticserve,
{'document_root': os.path.join(os.path.dirname(__file__), 'static')} ),
)

I did the following changes to my project/urls.py and it worked for me
Add this line :
from django.conf.urls import url
and add :
url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT, }),
in urlpatterns.

Although it's not safest, but you can change in the source code. navigate to Python/2.7/site-packages/django/conf/urls/static.py
Then edit like following:
if settings.DEBUG or (prefix and '://' in prefix):
So then if settings.debug==False it won't effect on the code, also after running try python manage.py runserver --runserver to run static files.
NOTE: Information should only be used for testing only

Related

Django isn't serving static files

I'm working with an existing (and previously functional) Django site. We recently upgraded from Django 1.8.13 to 1.10 and our WSGI is Gunicorn. It works fine when hosted from my development machine, but when deployed, all static resources (on the admin and the main site) yield 404's with the message, Directory indexes are not allowed here.
Our settings.py contains the following:
INSTALLED_APPS = (
...
'django.contrib.staticfiles',
...
)
DEBUG = True
STATIC_URL = '/static/'
PROJECT_DIR = os.path.dirname(os.path.dirname(__file__))
STATICFILES_DIRS = (
os.path.join(PROJECT_DIR, 'static'),
)
STATIC_ROOT = os.path.join(PROJECT_DIR, 'static_resources')
The directory structure looks like this:
/my-project-name
/my-project-name
server.py
settings.py
urls.py
wsgi.py
...
/static
/static_resources
manage.py
Django does not serve static files in production mode (DEBUG=False). On a production deployment that's the job of the webserver. To resolve the problem:
run python manage.py collectstatic
in your web server configuration point the /static folder to the static folder of Django
Don't just turn DEBUG on, it would be dangerous!
Try to change os.path.join(PROJECT_DIR, '../static') to os.path.join(PROJECT_DIR, 'static') and STATIC_ROOT = os.path.join(PROJECT_DIR, '../static_resources') to STATIC_ROOT = os.path.join(PROJECT_DIR, 'static_resources'). It will solve your problem.
The answer was very subtle. When I upgraded Django to 1.9 and ran the server, it gave the following warning:
?: (urls.W001) Your URL pattern '^static/(?P<path>.*)$' uses include with a regex ending with a '$'. Remove the dollar from the regex to avoid problems including URLs.
In urls.py, my urlpatterns list contained:
url(r'^static/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.STATIC_ROOT,
}),
I changed it to:
url(r'^static/(?P<path>.*)/', 'django.views.static.serve', {
'document_root': settings.STATIC_ROOT,
}),
This eliminated the warning but caused static resources to stop loading.
It needed to be:
url(r'^static/(?P<path>.*)', 'django.views.static.serve', {
'document_root': settings.STATIC_ROOT,
}),
It's still a mystery to me why this worked on my dev machine (a Macbook), as well as another on the team's dev machine (a windows laptop), but not on our Linux server. But, it works now, so I'm done trying to figure it out.

Getting 404 for all static files during WSGI setup with django

I have the following directory structure
-----root
|___docpd
|__docpd (contains settings.py, wsgi.py , uwsgi.ini)
|__static
During my vanilla django setup in dev environment , everything was fine (all static files used to load). But now after setting up uwsgi, i found that none of my static files are being loaded(I get a 404 error).
What have i tried ?
1. Read alot of stack overflow questions about this error and none could solve my problem.
2. I adjusted the python path with paths to my project and they seem to get added as i printed them out in the settings.py file, but still no luck.
Some code
uwsgi.ini
[uwsgi]
chdir=/home/ubuntu/docpad/Docpad/
wsgi-file=/home/ubuntu/docpad/Docpad/Docpad/wsgi.py
master=True
pidfile=/tmp/project-master.pid
vacuum=True
max-requests=5000
daemonize=/var/log/uwsgi/docpad.log
wsgi.py
import os,sys
sys.path.append('/home/ubuntu/docpad/Docpad/')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Docpad.settings")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
settings.py
from sys import path
from os.path import abspath, dirname, join, normpath
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
print "Base dir = " , BASE_DIR
DJANGO_ROOT = dirname(abspath(__file__))
print "Root =",DJANGO_ROOT
SITE_ROOT = dirname(DJANGO_ROOT)
print "SITE =", SITE_ROOT
path.append(DJANGO_ROOT)
print "Path = ",path
print BASE_DIR
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'SECRET'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
TEMPLATE_DEBUG = True
PROJECT_PATH = os.path.join(BASE_DIR, os.pardir)
PROJECT_PATH = os.path.abspath(PROJECT_PATH)
TEMPLATE_PATH = os.path.join(PROJECT_PATH, 'Docpad/templates/')
print "TEMPLATES = ",TEMPLATE_PATH
# TODO make separate template_paths
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
TEMPLATE_PATH,
)
...
After i run my application, i get 404 for all static resources like css/js files.
UPDATE
When i do
python manage.py runserver 0.0.0.0:8000
the server starts serving the static files
But , this command
uwsgi --ini uwsgi.ini --http :8000
gives me the problem(not loading the static files).
I am totally clueless right now,have been trying various alternatives but no luck.
If anybody could help, it'll be great.
I solved problem by doing below:
add
check-static = /your django dir/
in uwsgi.ini file.
it works for me!
Suppose your static assets are under /customers/foobar/app001/public. You want to check each request has a corresponding file in that directory before passing the request to your dynamic app. The --check-static option is for you:
--check-static /customers/foobar/app001/public
http://uwsgi-docs.readthedocs.io/en/latest/StaticFiles.html
You could also do it like so:
uwsgi --ini uwsgi.ini --http :8000 --static-map /static=/path/to/staticfiles/
or just add this to your .ini file:
static-map = /static=/path/to/staticfiles
in settings
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.normpath(os.path.join(BASE_DIR, "static")),
)
in urls.py
urlpatterns = [
#urls
]+ static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
I don't know why, but it starts work when I replace this code:
if settings.DEBUG:
urlpatterns += [
url(r'^(?P<path>.*)$', 'django.contrib.staticfiles.views.serve'),
]
with this:
if settings.DEBUG:
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
in file urls.py
I have Django 1.8

Appfog Django admin css missing

I'm using http://appfog.com I have DEBUG = True and ADMIN_MEDIA_PREFIX = '/static/admin/'
The css for the admin is missing.
Django only serves static files if DEBUG=True and it is running the development server.
Documentation:
This view is automatically enabled and will serve your static files at STATIC_URL when you use the built-in runserver management command
[...]
To enable this view if you are using some other server for local development, you'll add a couple of lines to your URLconf. The first line goes at the top of the file, and the last line at the bottom.
Example:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
# ... the rest of your URLconf goes here ...
urlpatterns += staticfiles_urlpatterns()
Hope this helps
Using dbieber's Django template for appfog this is the approach that worked for me:
Create a directory for static files in your project directory, then set up a URL to have the appfog server serve these files:
cd <project>
mkdir static
In urls.py, make sure the urlpattern is set to include static files (this is already there if you use the template):
urlpatterns += patterns('',
...
url(r'^static/(?P<path>.*)$',
'django.views.static.serve',
{'document_root': settings.STATIC_ROOT),
)
Collect all static files into the static directory
python manage.py collectstatic
Deploy to appfog
af update <appname>

Django cannot find my media files (on development server)

The media is currently on my local development machine.
My MEDIA_ROOT, MEDIA_URL, ADMIN_MEDIA_PREFIX and are specified as below:
MEDIA_ROOT = os.path.join(os.path.dirname(__file__), "media")
MEDIA_URL = '/media/'
SITE_URL = 'http://localhost:80'
ADMIN_MEDIA_PREFIX = '/media/admin/'
There is no 'admin' folder but that shouldn't make a difference I don't think.
In the urls.py file I have:
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
I am at a loss as to what I should do to get it working.
[I am trying to learn django and am working with an existing project that's pretty hairy]
You're mixing and matching pre and post-Django 1.3 static file handling. Originally all static files were served from MEDIA_URL, but Django 1.3 introduced the staticfiles contrib package and the associated STATIC_ROOT and STATIC_URL settings. django.views.static.serve utilizes the new staticfiles app, which you haven't set up.
Assuming you're running Django 1.3, first, you'll need to add 'staticfiles' to your INSTALLED_APPS. Then, you'll need to define STATIC_ROOT and STATIC_URL. The standard location is a project-root level directory named "static".
You'll also need to add the staticfiles template context processor:
TEMPLATE_CONTEXT_PROCESSORS = (
...
'django.core.context_processors.static',
)
This will make the STATIC_URL variable available in your templates, so you can reference your resources with something like {{ STATIC_URL }}css/style.css
All your static resources will also need to go into an app(s)-level directory named "static". The actual project-root level "static" directory is never directly used. It's simply the place where the collectstatic management command dumps all your static resources for use in production.
If you want project-wide static resources (not tied to any one particular app), you'll need an entirely separate directory (i.e. not the same as MEDIA_ROOT or STATIC_ROOT). I tend to use one named "assets". You'll then need to tell Django to look in here for static resources as well with the STATICFILES_DIRS setting:
STATICFILES_DIRS = (
os.path.join(os.path.dirname(__file__), 'assets'), # or whatever you named it
)
MEDIA_ROOT/MEDIA_URL are now only used for user uploads (e.g. any file created through FileFields and ImageFields, so you still need it, but you won't ever manually store anything there.
When you reach production, your webserver will need to serve both MEDIA_ROOT and STATIC_ROOT at MEDIA_URL and STATIC_URL, respectively. You'll also need to run:
$ python manage.py collectstatic
To make Django compile all your static files into the directory specified by STATIC_ROOT.
works with django 1.8 - 1.11:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
https://docs.djangoproject.com/en/1.11/howto/static-files/#serving-files-uploaded-by-a-user-during-development
note that Django documentation states that this is
not suitable for production use
(obviously unless you use if settings.DEBUG: part)
On development server, this page may help you.
https://docs.djangoproject.com/en/1.2/howto/static-files/
By adding follow code to urls.py:
if settings.DEBUG:
urlpatterns += patterns('',
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/path/to/media'}),
)
With python-django 1.7 I used
if settings.DEBUG:
urlpatterns = patterns('',
(r'^$', 'blenderx3d.first_step.views.index'),
(r'^media/(?P<path>.*)$','django.contrib.staticfiles.views.serve'),)

Turn off caching of static files in Django development server

Is there an easy way to turn off caching of static files in Django's development server?
I'm starting the server with the standard command:
$ python manage.py runserver
I've got settings.py configured to serve up static files from the /static directory of my Django project. I've also got a middleware class that sets the Cache-Control header to must-revalidate, no-cache for development, but that only seems to affect URLs that are not in my /static directory.
#Erik Forsberg's answer worked for me. Here's what I had to do:
Comment out the staticfiles app from INSTALLED_APPS in settings.py:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
#'django.contrib.staticfiles',
)
Leave my STATIC_URL variable set in settings.py:
STATIC_URL = '/static/'
Add an entry to my project's base urls.py:
# static files w/ no-cache headers
url(r'^static/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.STATIC_ROOT}),
Note that I'm also setting the Cache-Control headers in a middleware class nocache.py:
class NoCache(object):
def process_response(self, request, response):
"""
set the "Cache-Control" header to "must-revalidate, no-cache"
"""
if request.path.startswith('/static/'):
response['Cache-Control'] = 'must-revalidate, no-cache'
return response
And then including that in settings.py:
if DEBUG:
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'nocache.NoCache',
)
Django's contrib.staticfiles app automatically serves staticfiles for you by overriding the runserver command. With this configuration you can't control the way it serves the static files.
You can prevent the staticfiles app from serving the static files by adding the --nostatic option to the runserver command:
./manage.py runserver --nostatic
Then you can write an url config to manually serve the static files with headers that prevent the browser from caching the response:
from django.conf import settings
from django.contrib.staticfiles.views import serve as serve_static
from django.views.decorators.cache import never_cache
urlpatterns = patterns('', )
if settings.DEBUG:
urlpatterns += patterns('',
url(r'^static/(?P<path>.*)$', never_cache(serve_static)),
)
If you want your manage.py runserver command to have the --nostatic option on by default, you can put this in your manage.py:
if '--nostatic' not in sys.argv:
sys.argv.append('--nostatic')
Assuming you're using django.views.static.serve, it doesn't look like it - but writing your own view that just calls django.views.static.serve, adding the Cache-Control header should be rather easy.
Use whitenoise. There's a lot of issues with the static file serving in runserver and they're all already fixed in whitenoise. It's also WAY faster.
They've talked about just replacing the built-in static serving with it, but no one has gotten around to it yet.
Steps to use it in development...
Install with pip install whitenoise
Add the following to the end of settings.py:
if DEBUG:
MIDDLEWARE = [
'whitenoise.middleware.WhiteNoiseMiddleware',
] + MIDDLEWARE
INSTALLED_APPS = [
'whitenoise.runserver_nostatic',
] + INSTALLED_APPS
My very simple solution:
from django.contrib.staticfiles.views import serve
from django.views.decorators.cache import never_cache
static_view = never_cache(serve)
urlpatterns += static_view(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
In newer versions of Django a very simple solution is modify the project urls like so:
from django.conf.urls.static import static
from django.contrib.staticfiles.views import serve
from django.views.decorators.cache import cache_control
from django.conf import settings
# YOUR urlpatterns here...
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, view=cache_control(no_cache=True, must_revalidate=True)(serve))
I arrived at this by looking at how staticfiles modifies the urls automatically and just adding a view decorator. I really don't understand why this isn't the default as this is for development ONLY. The view is able to properly handle a "If-Modified-Since" HTTP header so a request is always made but contents are only transferred on changes (judged by looking at the modification timestamp on the file).
For this to work you must add --nostatic when using runserver, otherwise the above changes are simply ignored.
IMPORTANT EDIT: What I had before didn't work because I wasn't using --nostatic and the never_cache decorator also included no-store which meant unchanged files were always being re-transferred instead of returning 304 Not Modified
For newer Django, the way middleware classes are written has changed a bit.
Follow all the instructions from #aaronstacy above, but for the middleware class, use this:
class NoCache(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
response['Cache-Control'] = 'must-revalidate, no-cache'
return response
It's so simple if you are using Django 2.0+
Step-1 : Make 'django.contrib.staticfiles' as comment in settings.py(Project level)
INSTALLED_APPS = [
# 'django.contrib.staticfiles',
]
Step-2 : Import followings in urls.py (Project level)
from django.conf.urls.static import static
from django.contrib.staticfiles.views import serve
from django.views.decorators.cache import never_cache
from . import settings
Step-3 : Add following line in urls.py(project level) after urlpatterns
urlpatterns = [
]
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, view=never_cache(serve))
Make sure that STATIC_URL is declared in your settings.py
STATIC_URL = '/static/'
The staticfiles app implements serving of static files by overriding the runserver command. We can do the same: override this command again and implement a custom handler which turns off caching.
Note that your django application must be before django.contrib.staticfiles in INSTALLED_APPS, otherwise your command will be ignored.
# your_django_app/management/commands/runserver.py
from django.utils.cache import add_never_cache_headers
from django.contrib.staticfiles.handlers import (
StaticFilesHandler as BaseStaticFilesHandler,
)
from django.contrib.staticfiles.management.commands.runserver import (
Command as RunserverCommand,
)
class StaticFilesHandler(BaseStaticFilesHandler):
def serve(self, request):
response = super().serve(request)
add_never_cache_headers(response)
return response
class Command(RunserverCommand):
def get_handler(self, *args, **options):
handler = super().get_handler(*args, **options)
# Check that serving static files is enabled
if isinstance(handler, BaseStaticFilesHandler):
# If yes, replace the original handler with our custom handler
handler = StaticFilesHandler(handler.application)
return handler
This has nothing with Django, because nothing changed after I reinstall Django using pip.
This is the behavior of browser, so you just need to clear cached images files of your browser.
Ref
Chrome Clear cache and cookies

Categories