Reputation: 7917
I want to run my django project under gunicorn on localhost. I installed and integrated gunicorn. When I run:
python manage.py run_gunicorn
It works but there are no any static files (css and js)
I disabled debug and template_debug in settings.py (made them false), but it is still same. Am I missing something?
I call statics like:
{{ STATIC_URL }}css/etc....
Upvotes: 120
Views: 115672
Reputation: 7450
When in development mode and when you are using some other server for local development add this to your urls.py
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
# ... the rest of your URLconf goes here ...
urlpatterns += staticfiles_urlpatterns()
Note that staticfiles_urlpatterns()
will only work when DEBUG = True
is set in your settings.py
.
More info here
When in production you never, ever put gunicorn in front. Instead you use a server like nginx which dispatches requests to a pool of gunicorn workers and also serves the static files.
See here
Upvotes: 224
Reputation: 15421
While you're able to use Django to serve static files in development mode with the app django.contrib.staticfiles
, that is not suitable for production use.
In order to serve static files, as Jamie Hewland says, normally one routes all the requests to /static/ using Nginx
location /static/ {
alias /path/to/static/files;
}
Also, and as coreyward says about Gunicorn / Unicorn
was not designed to solve the suite of problems involved in serving files to clients
Same line of reasoning applies if you consider other WSGI server like uWSGI instead of Gunicorn. In uWSGI documentation
it’s inefficient to serve static files via uWSGI. Instead, serve them directly from Nginx and completely bypass uWSGI
So, serving static files in production is something to be done by NGINX, not by Django or other WSGI servers.
Another way is to serve your static files in production is using WhiteNoise library which is very easy to setup (you might want to use a CDN so that most requests won't reach the Python app). As Miguel de Matos says, you just have to
Collect static
python manage.py collectstatic
Installing whitenoise
pip install whitenoise
Add the following STATICFILES_STORAGE
in settings.py
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
Add the following to your MIDDLEWARE
in settings.py (as mracette notes, "According to the whitenoise docs you should place the middleware after django.middleware.security.SecurityMiddleware
")
`MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
...
]
Upvotes: 14
Reputation: 3712
If you are using Apache/Gunicorn then here is how I set mine up.
In your Django root dir (with manage.py
), create dirs mkdir -p django_static/static
In your project settings.py
set the following:
DEBUG = False
INSTALLED_APPS = [..., 'django.contrib.staticfiles', ...]
STATIC_URL = 'static/'
STATIC_ROOT = os.path.join(BASE_DIR, "django_static", "static")
Run python manage.py collectstatic
. This will output static content to django_static/static
Start your gunicorn
server with gunicorn your_project_name.wsgi
(plus options)
Assuming you have default global Apache settings, you'll need to create a soft link from /var/www
to your static dir:
sudo ln -s /path/to/your_django_project/django_static /var/www/your_django_project_static
For your domain www.example.com
that you wish to point to your Django app, configure the following virtual host in apache in order to proxy all requests submitted to https://www.example.com
onto 127.0.0.1:8000
except for www.example.com/static/
routes (in which case, serve files to such requests from django_static
):
<VirtualHost *:443>
ServerName www.example.com
DocumentRoot /var/www/your_django_project_static
<Location "/">
ProxyPreserveHost On
ProxyPass http://127.0.0.1:8000/
ProxyPassReverse http://127.0.0.1:8000/
</Location>
<Location "/static/">
ProxyPass "!"
</Location>
</VirtualHost>
Voila!
Upvotes: 1
Reputation: 3027
The gunicorn should be used to serve the python "application" itself, while the static files are served by a static file server ( such as Nginx ).
This is an excerpt from one of my configurations:
upstream app_server_djangoapp {
server localhost:8000 fail_timeout=0;
}
server {
listen < server port goes here >;
server_name < server name goes here >;
access_log /var/log/nginx/guni-access.log;
error_log /var/log/nginx/guni-error.log info;
keepalive_timeout 5;
root < application root directory goes here >;
location /static {
autoindex on;
alias < static folder directory goes here >;
}
location /media {
autoindex on;
alias < user uploaded media file directory goes here >;
}
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
if (!-f $request_filename) {
proxy_pass http://app_server_djangoapp;
break;
}
}
}
Some notes:
In closing: while it is possible to serve static files from gunicorn ( by enabling a debug-only static file serving view ), that is considered bad practice in production.
Upvotes: 25
Reputation: 382442
Whitenoise
Post v4.0
http://whitenoise.evans.io/en/stable/changelog.html#v4-0
The WSGI integration option for Django (which involved editing wsgi.py) has been removed. Instead, you should add WhiteNoise to your middleware list in settings.py and remove any reference to WhiteNoise from wsgi.py. See the documentation for more details. (The pure WSGI integration is still available for non-Django apps.)
Pre v4.0
Heroku recommends this method at: https://devcenter.heroku.com/articles/django-assets:
Your application will now serve static assets directly from Gunicorn in production. This will be perfectly adequate for most applications, but top-tier applications may want to explore using a CDN with Django-Storages.
Install with:
pip install whitenoise
pip freeze > requirements.txt
wsgi.py
:
import os
from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "free_books.settings")
application = get_wsgi_application()
application = DjangoWhiteNoise(application)
Tested on Django 1.9.
Upvotes: 40
Reputation: 1620
Since Django 1.3 there is django/conf/urls/static.py that handle static files in the DEBUG mode:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Read more https://docs.djangoproject.com/en/2.0/howto/static-files/#serving-static-files-during-development
Upvotes: 2
Reputation: 9906
I've used this for my development environment (which uses gunicorn):
from django.conf import settings
from django.contrib.staticfiles.handlers import StaticFilesHandler
from django.core.wsgi import get_wsgi_application
if settings.DEBUG:
application = StaticFilesHandler(get_wsgi_application())
else:
application = get_wsgi_application()
And then run gunicorn myapp.wsgi
. This works similar to @rantanplan's answer, however, it does not run any middleware when running static files.
Upvotes: 30