In Django 2.2, when I have DEBUG=True, all my static files render fine. But when I set DEBUG=False to test my production settings, all static file URLs suddenly return 404 errors.
I have a project structure like:
myproject/
myproject/
settings.py
urls.py
manage.py
static/
thumbnails/
image.png
My relevant static settings in settings.py:
STATIC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'static'))
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
ROOT_URLCONF = 'myproject.urls'
STATIC_URL = '/static/'
DEBUG = False
And my urls.py looks like:
import os
from django.contrib import admin
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Why does a url like http://localhost:8000/static/thumbnails/image.png work fine when debug is on, but return a 404 when debug is off?
In production, you should run python manage.py collectstatic, and actually serve your static files from somewhere.
If you look at the docs for static files, you'll see
Serving the files
In addition to these configuration steps, you’ll also need to actually
serve the static files.
During development, if you use django.contrib.staticfiles, this will
be done automatically by runserver when DEBUG is set to True (see
django.contrib.staticfiles.views.serve()).
This method is grossly inefficient and probably insecure, so it is
unsuitable for production.
See Deploying static files for proper strategies to serve static files
in production environments.
You should set the STATIC_ROOT in you production settings to a folder on you web server, and configure your webserver to point your STATIC_URL to that folder. See here.
In your case, it's seems you have taken all these steps, except actually serving your static files. You can do this by pointing your web server to the correct folder, or serving you static files from a CDN or other solution. Here's how to do it using apache
Django was never meant to replace web servers. From the Django docs:
Django doesn’t serve files itself; it leaves that job to whichever Web server you choose.
This method is grossly inefficient and probably insecure, so it is unsuitable for production.
On localhost with DEBUG = TRUE it deploys the static file. While on production, you should use your web server(Apache, 'Nginx' etc) to deploy static files.
Just list the static directory in the configuration file of your web server. More detailed instructions regarding deployment can be found here
Related
Since I had started Django, I'm tackling some ridiculous problems. Recently, when I start a new project and I run it on the server, Django's admin CSS is not loaded. The last project I ran on the server, after a while it was okay, and the real Django admin template was there and the CSS was loaded and it was working. But this time again the same problem happened and I don't know how to solve it cause the project here is the photo is raw, with no special code.
I don't know if it's Chrome problem or not, but I have tried it on other browsers and it was the same thing.
I would be glad if you can help me
the answer I found was to change STATIC_URL = 'static/' in settings.py to STATIC_URL = '/static/'. Only one '/' may change your whole admin appearance. This problem may not happens to everyone but running code in Pycharm, I had been tackling it for such a long time.
If this problem is happening locally, then just change your settings.py
DEBUG = True
#...
#...
STATIC_ROOT = YOUR_STATIC_ROOT_DIRECTORY
Then run collectstatic, make sure you have a proper STATIC_ROOT directory which is also in your settings.py file
python manage.py collectstatic
If you have deployed your app on a production server then, you have to follow certain things in order to get stylesheet and javascript files.
Firstly
In your urls.py you need to add this code
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + \
static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Then you have to use a third-party media file server(CDN) Like AWS S3 or you can serve your css, js or media files from your Django server
If you don't want to use AWS S3, then you can either send css/js using your django app (which is not ideal to do), or you can use nginx or apachee to send your css/js
For Nginx to send js/css
You have to add a Static and Media File Root that can be accessed by your django application, I usually use /var/www/ to serve static and media from any Linux server
STATIC_ROOT = '/var/www/static'
MEDIA_ROOT = 'var/www/media'
Then if you are using nginx
server {
server_name domainname.com;
access_log off;
location /static/ {
root /var/www/static;
}
location /media/ {
root /var/www/media;
}
If it is still not working, then your django app might not be able to use the given static_root and media directory, make sure your app has access to them
If you want to send your js/css from your django app (Better not to do in production)
Then
To install whitenoise
pip install whitenoise
In your settings file
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
# ...
]
Based on all I've read in the docs and on various s/o questions, Django cannot serve static files in production (when DEBUG = False) and they have to be served by a web server. Yet, when I run my code my static files are showing up just fine even with debug turned off. This concerns because as we move to production, I can't imagine it will continue to serve those files without me setting it up so they're served by a web server and I don't want my dev environment to not give me an accurate picture of how it will work in production.
How is it possible that my app is serving static files without a web server with DEBUG = False? I've included the relevant blurbs in my settings.py file, urls.py file, and my command to collectstatic in my Dockerfile. It also serves the static files just fine when I have RUN python manage.py collectstatic and STATIC_ROOT commented out.
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
] + static(settings.STATIC_URL, document_root=settings.STAT)
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
settings.py
STAT = os.path.join(BASE_DIR, 'static')
DEBUG = False
STATIC_URL = '/static/'
STATICFILES_DIRS = [STAT]
STATIC_ROOT = os.path.join(BASE_DIR, 'prod_static')
Dockerfile
RUN python manage.py collectstatic --noinput
Django is serving all contents of 'static' folder because of this definition:
] + static(settings.STATIC_URL, document_root=settings.STAT)
The command collectstatic does not need this definition, as it searches for all folders present in STATICFILES_DIRS and copies all static assets to your STATIC_ROOT.
Also, you should change this:
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STAT)
Like this, on development you are serving static folder with django and on production you will need a web server to serve prod_static folder.
please help me on this docker django configuration for serving static files.
my Django project running on Docker got some issues with delivering static files.
All static files for admin view is loading fine, but static files for client web view is throwing 404 Not found Error.
This is my docker.yml configuration details:
web:
build: ./web
expose:
- "8000"
links:
- postgres:postgres
volumes:
- ./web:/usr/src/app
ports:
- "8000:8000"
env_file: .env
command: python manage.py runserver 0.0.0.0:8000
postgres:
image: postgres:latest
volumes:
- /var/lib/postgresql
ports:
- "5432:5432"
update
This is the admin static file url will look like :
http://developer.com:8000/static/admin/css/base.css
and this is how client static file url looks like:
http://developer.com:8000/static/css/base.css
Where those admin folder in static directory is creator by running django command collectstatic
I have used this setting previously, and was working fine. But when I moved the project root folder to another directory seems have this issue.
I am totally stuck here, many many thanks for all your help and feedback.
This was issue with the STATICFILES_DIRS configuration in the settings.py file.
This setting defines the additional locations the staticfiles app will traverse if the FileSystemFinder finder is enabled, e.g. if you use the collectstatic or findstatic management command or use the static file serving view.
Following was the configuration in my settings.py:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, "static")
Now I updated this code to:
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
And every files is loading fine.
Reference Link
Use Whitenoise to make your life easier when dealing with static files in django.
1.If you are using docker-compose,add whitenoise to your requirements.txt file:
whitenoise==3.3.1
2.Add whitenoise to your middleware apps inside settings.py
MIDDLEWARE_CLASSES = [# 'django.middleware.security.SecurityMiddleware','whitenoise.middleware.WhiteNoiseMiddleware',# ...]
make sure that you add this below your security.SecurityMiddleware app
3.Finally, change the following variables inside settings.py
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
STATICFILES_DIRS = (os.path.join(BASE_DIR,'<app_name>/static'),os.path.join(BASE_DIR, 'static'),)
Be sure to replace with the name of your app. Note that this only applies if your static files are stored in(for example) my_project/app/static/app/.
Otherwise if your static folder is located in my_project/app/static:
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)
Lastly disable the built-in django static file server as follows:
INSTALLED_APPS = [
# ...
'whitenoise.runserver_nostatic',
'django.contrib.staticfiles',
# ...]
As you have moved your project to another directory, there is a possibility that the path of your static directories are also different now. Django in most scenarios use apache, nginx or some other web servers to serve static files. One point to notice is that your static directory should be accessed publicly. I had gone through a problem like this before. What I did was I moved static dir to document root mentioned in apache config file.
So move your static files to the doc root of apache and update static directories in settings.py to refer to the static directory in your apache doc root. I hope this helps.
I am trying to deploy my django app on heroku. All the static files are served by whitenoise and are migrated successfully. But how do I get my media files that are uploaded using ImageField to display during production.
my settings.py
STATIC_URL = '/static/'
STATIC_ROOT = 'C:/Users/Sak/mpro/feat/static/'
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
wsgi.py
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mpro.settings")
application = get_wsgi_application()
try:
from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise
application = get_wsgi_application()
application = DjangoWhiteNoise(application)
from dj_static import Cling
application = Cling(get_wsgi_application())
except:
pass
urls.py
urlpatterns = [
url(r'^', include('feat.urls', namespace="feat")),
url(r'^admin/', include(admin.site.urls)),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
All my media files are uploaded to base_dir/media/media and when whitenoise collects static files it only collects files at STATIC_ROOT, so how do I get my media files deployed. When I run heroku run ls I can see the folder media.
So, first of all it's important to realise that if you have a bunch of files that are part of your project (including things like images and such) and are deployed along with it, they are more likely to be static files than media files in Django parlance.
Media files in Django are for runtime uploaded files. They will generally be stored with a corresponding db entry such as models.ImageField(upload_to='/photos') but that isn't necessarily so.
Your media setup is wrong for Heroku, as you shouldn't be writing to a directory on the server anyway (this is what you are telling Django to do with MEDIA_ROOT = os.path.join(BASE_DIR, "media").
Most commonly you would instead use an S3 bucket for media on Heroku. This is a fairly comprehensive explanation of that. You can probably skip the bit about CORS and go for open permissions on the bucket (depending on your use case). The important bits are:
# settings.py
# Tell django what URL to server your media from
MEDIA_URL = "https://%s/" % AWS_S3_CUSTOM_DOMAIN
# Tell Django to use the boto storage backend to save media files.
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
If you want to use S3 for static AND media storage, the link explains that too.
You might want to look at this repo for a pretty comprehensive run-down of the AWS settings and what they do, plus a nicely wrapped package to do some of it for you.
More generally I found Django Herokuify exceptionally useful for all the boilerplate on Heroku.
I'm trying to push my Django project to Heroku, but it isn't loading the staticfiles.
I used this to setup the things, everything is fine but I'm not able to fix the issue with static files.
My directory structure is like this
help_the_needy
help_the_needy
__init__.py
settings.py
urls.py
views.py
wsgi.py
manage.py
Procfile
requirements.txt
static
css
font-awesome
fonts
img
js
templates
base.html
display_list2.html
index.html
Here is the complete code (all files).
This is my settings.py.
I tried alot of things to fix this, but nothing seems to work.
When I push it does copy static files but it's not loading them.
Can someone please point me to my mistake? Where is it wrong?
I have been dealing with the same problem too. And here are the 2 things that I changed in my code.
(I'm using Django 1.7)
1) settings.py
I add these lines to the setting files
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
TEMPLATE_DIRS = (
os.path.join(BASE_DIR, 'templates'),
# Add to this list all the locations containing your static files
)
STATIC_ROOT: this tells Django where to (a) put the static files when you run python manage.py collectstatic and (b) find the static files when you run the application
TEMPLATE_DIRS: this tells Django where to look for your static files when it search for statics files when you run python manage.py collectstatic
2) wsgi.py
Originally my file was:
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xxxx.settings")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
And I changed it to:
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xxxx.settings")
from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise
application = get_wsgi_application()
application = DjangoWhiteNoise(application)
Read here for more information on whitenoise: https://devcenter.heroku.com/articles/django-assets#whitenoise
Also, remember to install whitenoise:
pip install whitenoise==2.0.6
Before deploying the project, run:
python manage.py collectstatic
This will create a folder indicated by STATIC_ROOT (declared in your settings.py), containing all your static files.
Since it's been a few years since this was posted (and it still pops up when I search for the issue), here's what worked for me in Django 3.2.
pip install whitenoise
Make sure in settings.py you have
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
# Extra places for collectstatic to find static files.
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
Add whitenoise to your Middleware:
MIDDLEWARE = [
'whitenoise.middleware.WhiteNoiseMiddleware',
]
Make sure the directory you specified as the STATIC_ROOT (staticfiles) exists in your base directory and is not empty.
After that, I committed the changes and Heroku was able to build the static files and everything worked fine.
pip install whitenoise
Add whitenoise to requirement.txt.
and also add whitenoise in the middleware of settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', #add whitenoise
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Follow the steps in https://devcenter.heroku.com/articles/django-assets
Your STATICFILES_DIRS setting is wrong. It should be pointing to the actual location of the "static" directory containing the files:
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
It looks like django don't know where your static_root is.
This folder is autogenerated when you fire manage.py collectstatic
Make sure that the folders static and templates are inside your django app. You didn't created a django app to put this folders into. You created a django project the next step is to create a django app with something like this python manage.py startapp polls
# Absolute filesystem path to the Django project directory:
DJANGO_ROOT = dirname(dirname(abspath(__file__)))
# Absolute filesystem path to the top-level project folder:
SITE_ROOT = dirname(DJANGO_ROOT)
STATIC_URL = '/static/'
STATIC_ROOT = normpath(join(SITE_ROOT, 'static_root'))
Your urls.py file lacks the setting to manage and route requests for static resources.
in order to provide access to static resorces you must add to urlpatterns of urls.py:
urlpatterns += patterns('',
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
)