I've heard I should use Apache for serving static files in a production environment. I'm having some problems understanding how I'm supposed to do that though. My project's static URL is /static/, and django.contrib.admin's static path is /static/admin/. Those are two completely separate directories on my server, and I can hardly do this:
Alias /static /path/to/site.com/static
Alias /static/admin /usr/local/.../django/contrib/admin/media
Since they overlap.
How am I supposed to do this? Do I really have to copy the contrib admin static folder into my own?
Firstly, no-one says you have to serve your admin static files from the same base path as the others. You can set ADMIN_MEDIA_PREFIX to whatever you like.
However, surely the easiest thing is just to add a symlink from your static folder to django/contrib/admin/media.
Common solution is using /media/ for admin media static files, so it could be in settings.py
ADMIN_MEDIA_PREFIX = '/media/'
and in virtual host config:
Alias /media /path/to/django/contrib/admin/media/
<Location /media>
SetHandler None
</Location>
You can reverse the order of the Alias entries and Apache will parse it as intended:
Alias /static/admin /usr/local/.../django/contrib/admin/media
Alias /static /path/to/site.com/static
This is because when Apache loads its configuration, it stores entries from a top down perspective. So it first tries to match /static/admin, then if the URI doesn't match, it then tries to match /static.
Related
I have a Django instance set up on an Apache server running through uWSGI hunky dory. Everything looks perfect on my local machine when I use python manage.py runserver. Unfortunately, the minute I uploaded the files to my pre-prepared production server, it refused to load all of Django's built-in static files, returning a 404 and I have no idea why...
The url that is being queried is listed as www.mysite.com/static/admin/css/fonts.css and is similar for the admin backend(css/base.css,css/dashboard.cssandcss/responsive.css). At first I thought it might be something wrong with the packages so I force-reinstalled Django but no go. Still not loading...
Here is my uWSGI config .ini:
[uwsgi]
chdir = /path/to/top/level/mysite
module = mysite.wsgi:application
env = DJANGO_SETTINGS_MODULE=mysite.settings
master = true
pidfile = /path/to/project.pid
socket = 127.0.0.1:49152
; Dont use UNIX sockets as it confuses the proxy and alters the request
: URL's. Current Apache version cant handle it.
; socket=/var/run/swerth_django.sock
processes = 5
harakiri = 20
post-buffering = 1
max-requests = 5000
vacuum = true
home = /path/to/top/level/Virtualenv/directory
daemonize = /path/to/uWSGI.log
env = LANG=en_US.UTF-8
enable-threads = true
And I have included Static root and url as follows (comments were for my own understanding):
#The URL of which the static files in STATIC_ROOT directory are served
STATIC_URL = '/static/'
#The absolute path to the directory where ./manage.py collectstatic
# will collect static files for deployment.
STATIC_ROOT = '/home/swerth/public_html/swerth/static'
It is worth mentioning however, I do not have any static files of my own as of yet. I am not at that point in development. I simply want to use the templates shipped with Django.
Edit:
Ok, so I did some research and managed to narrow it down a bit (Thank you to #Alasdair for pointing out a particular page in the Django docs). It seems that I can run python manage.py collectstatic just fine and it imports all the files I need into www.mysite.com/static. For some reason however, django dosnt seem to be 'seeing' the files as they don't render in browser (404 not found).
In light of this I am assuming its my config in settings.py?
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/
#The URL of which the static files in STATIC_ROOT directory are
#served
STATIC_URL = '/static/'
#The absolute path to the directory where ./manage.py collectstatic
# will collect static files for deployment.
STATIC_ROOT = os.path.join(BASE_DIR, "static")
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
My Apache is set up as a reverse proxy using the following config:
RewriteEngine off
ProxyPreserveHost on
ProxyPass "/" "uwsgi://127.0.0.1:49152/"
ProxyPassReverse "/" "uwsgi://127.0.0.1:49152/"
Am I doing this wrong or something? (P.s. I am trying to avoid having to edit the HTML files static file link as I really would prefer to know WHAT I'm doing wrong so it doesn't happen again since Django should be able to serve straight from www.mysite.com/static)
Edit Round 2:
Ok, so I did as suggested and tried to set up my proxy to exclude the static directory and just serve the files normally and added an alias to map the URL to the actual directory but it still isn't working properly. It seems to completely ignore my ProxyPass exception and sends it off to Django even though I included it above the less specific rule? Interesting issue, when I specify /admin/ instead of just / for the less-specific ProxyPass, it only proxies that URL to Django, however, all of a sudden Django kicks up a 404 for /admin/. Additionally, I get a 403 forbidden for the static files I was trying to serve?!?! My current .conf looks like this:
Alias /static/ /home/swerth/public_html/swerth/static/
<Directory /home/swerth/public_html/swerth/static/>
Require all granted
</Directory>
<Directory /home/swerth/public_html/swerth/swerth/>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
ProxyPreserveHost on
ProxyPass /whm-server-status/ !
ProxyPass /static/ !
ProxyPass / uwsgi://127.0.0.1:49152/
ProxyPassReverse / uwsgi://127.0.0.1:49152/
This is probably because you've not set up Apache to serve your static files. Try doing the following
Go to your 'static' file folder and get the absolute path to that folder using pwd. Looks like /home/swerth/public_html/swerth/static in your case. Also make sure that the user running the Apache httpd's process has read access to the static folder.
Now edit your VirtualHost by doing
sudo nano /etc/apache2/sites-available/000-default.confsudo nano /etc/apache2/sites-available/000-default.conf
Replace 000-default.conf with your own if you're using a different config file.
Add the following to the virtual hosts block:
<VirtualHost *:80>
. . .
Alias /static /home/swerth/public_html/swerth/static
<Directory /home/swerth/public_html/swerth/static>
Require all granted
</Directory>
. . .
</VirtualHost>
Also make sure you place this above your uwsgi <Directory> part
4. Restart apache by doing sudo systemctl restart apache2
This is a good tutorial I found on how to deploy a Django app to production.
Hope this helps.
Is there a way to serve 2 or more static directories from Apache? I am using Django and it works fine with 1 static path; when I put 2 it ignores the 2nd.
I don't want to use collecstatic. Just trying to setup my development environment and I like to keep my statics in each app separately. I know in production this will change.
Here is my Apache httpd.conf code:
#games app
Alias /static/ "C:/nerd_project/nerd/games/static/"
<Directory "C:/nerd_project/nerd/games/static">
Require all granted
</Directory>
#ice_cream app
Alias /static/ "C:/nerd_project/nerd/ice_cream/static/"
<Directory "C:/nerd_project/nerd/ice_cream/static">
Require all granted
</Directory>
games app works; the css and images load
ice_cream app does not load and is ignored
You are trying to Alias same URL path /static/ to two directories. That's why it's failing.
Django has pretty fine documention on Serving static files during development.
Check STATICFILES_DIRS settings docs to serve static files from multiple directories.
If you are trying to serve multiple projects static you may consider VirtualHost.
I was also having the same problem till today morning and landed on this page to understand why my static file configs were failing.
You can serve multiple apps with multiple static locations.
See how I have two Flask app and one Django app running and static files being served from different locations for all.
ServerName ec2-52-20-211-238.compute-1.amazonaws.com
# logs configuration
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
WSGIDaemonProcess aira threads=5
WSGIScriptAlias /aira /var/www/aira/aira/aira/aira.wsgi
Alias /aira/static/ /var/www/aira/aira/aira/static/
<Directory /var/www/aira/aira/aira/>
Order allow,deny
Allow from all
</Directory>
WSGIDaemonProcess ama threads=5
WSGIScriptAlias /ama /var/www/AMA/ama.wsgi
Alias /ama/static/ /var/www/AMA/static/
<Directory /var/www/AMA>
Order allow,deny
Allow from all
</Directory>
WSGIDaemonProcess realestatesurvey threads=5
WSGIScriptAlias /RealEstateSurvey /var/www/RealEstateSurvey/mydata/wsgi.py
Alias /RealEstateSurvey/static/ /var/www/RealEstateSurvey/mydata/static/
<Directory /var/www/RealEstateSurvey/mydata/static>
Order allow,deny
Allow from all
</Directory>
For flask template just use
For Django:
STATIC_URL = '/RealEsatateSurvey/static'
in html files:-
I can give a much more easier way to solve this issue that I learned about recently.
If you don't want to serve your static files with Nginx or a apache, but from different apps or folders you can install a pip module called whitenoise in your virtual environment.
Refer this: whitenoise docs
And then just add this in middlware before the sessionmiddleware in your settings.py file.
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', # Serve static in production without nginx or apache
'django.contrib.sessions.middleware.SessionMiddleware',
........
]
Then finally you can remove those Alias statements for rendering static files from your httpd.conf file. Make migrations and restart the server, your problem will be solved.
I figured out EXACTLY what needs to be done to serve multiple static directories using Apache.
This page https://docs.djangoproject.com/en/1.8/howto/static-files/ mentions this:
"Also this helper function only serves the actual STATIC_ROOT folder; it doesn’t perform static files discovery like django.contrib.staticfiles."
Adding + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) to the urls.py did not load the css and images. You have to read a bit more carefully and go to this page:
https://docs.djangoproject.com/en/1.8/ref/contrib/staticfiles/#django.contrib.staticfiles.views.serve
I added the following to the my urls.py and now IT WORKS:
from django.conf import settings
from django.contrib.staticfiles import views
if settings.DEBUG:
urlpatterns += [
url(r'^static/(?P<path>.*)$', views.serve),
]
I simply commented out the alias and directories pointing to the 2 static directories in Apache's httpd.conf file.
Of course this is strictly for a development server only as I like to keep my statics in each app.
I don't know what's wrong in my virtualhost for django project but the simply question is no matter what modification I do over this file stills output the same in error log from apache and not load any css or js files, what I can see is that Apache is looking for static and media file in the root web folder: /var/www
[Fri May 30 00:58:08 2014] [error] [client 192.168.1.145] File does not exist: /var/www/static, referer: http://192.168.1.143/dgp/login/
I set up virtual host file as follows:
WSGIPythonPath /var/www/dgp_python2_7/bin/python2.7:/var/www/dgp_python2_7/lib/python2.7/site-packages
WSGIScriptAlias /dgp /var/www/dgp/dgp/dgp/wsgi.py
<VirtualHost 127.0.0.1:80>
ServerName www.dgp.dev
ServerAlias dgp.dev
AliasMatch ^/([^/]*\.css) /var/www/dgp/dgp/static/$1
Alias /media/ /var/www/dgp/dgp/media/
Alias /static/ /var/www/dgp/dgp/static/
Alias /images/ /var/www/dgp/dgp/images/
<Directory /var/www/dgp/dgp/static/>
Order deny,allow
Allow from all
</Directory>
<Directory /var/www/dgp/dgp/media/>
Order deny,allow
Allow from all
</Directory>
ErrorLog /var/www/dgp/dgp/error.log
CustomLog /var/www/dgp/dgp/access.log combined
</VirtualHost>
And in settings.py STATIC_ROOT with '/var/www/dgp/dgp/static/' where is located all the css content.
How can I tell apache or Django to looking for the proper directory '/var/www/dgp/dgp/static/'? It's driving me crazy, I don't understand how something so elemental in development it's so complex for production.
Regards!
Edit with the solution
The really problem was that I didn't disable the default site for Debian Apache (that is the version I'm working for) and has another method for stablish virtualhost, at beginning we have to disable default site with the follow command: a2dissite defaultand everything works now like a charm!
You can tell where your static files are being looked for in your project's rendered html. Just view the source in your browser and look for a stylesheet or javascript include, what is the full path to the file?
My guess, you have to run Django's collect static script, which will collect all the static scripts in all of your project's app and put them into one location. This is a core part of deploying Django projects and unavoidable if you use multiple "apps" in your project.
in your terminal go to the Django projects root folder and type this:
python manage.py collectstatic
Read more at https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/
I just configured my first django server for a very basic django-website. I'm using Django 1.4 and Nginx 1.0.14 with supervisor and gunicorn.
The problem is that Nginx is not serving the static files as suposed, but I don't know the why because is my first time using it.
This is the path where really lives my static files:
/home/cristian/envs/santalupe.com/santalupe/santalupe/static
And this is the setting I've in my nginx config file:
# Django admin media.
location /media/ {
autoindex on;
alias /home/cristian/envs/santalupe.com/lib/python2.7/site-packages/django/contrib/admin/static/;
}
# Site media
location /static/ {
autoindex on;
alias /home/cristian/envs/santalupe.com/santalupe/santalupe/static/;
}
Please let me know what I need to do in this case because I have not idea about the real problem.
You aren't serving the admin media from Nginx, just normal media. Try something like:
location /admin/media/ {
# this changes depending on your python version
root /home/cristian/envs/santalupe.com/lib/python2.7/site-packages/django/contrib;
}
Note how there's no trailing slash and the path ends at contrib. I'm using almost exactly this code successfully in production.
Maybe manage.py collectstatic on server help you?
Here is good description on right solution https://docs.djangoproject.com/en/dev/howto/static-files/#serving-static-files-in-production
I have a site I made with Django, and I'm trying to deploy it on an Apache server I have lying around (using mod_wsgi as recommended by the official docs) and for the most part, everything's going great. I am having a problem getting Apache to correctly serve the static files associated with my project. Judging by comparing the source of the rendered HTML with my server's file structure, I would say that my app is requesting the right files from the right locations, but for whatever reason Apache throws me a 404. Here's my config for apache:
<VirtualHost *:80>
ServerName book
ServerAlias www.book.dev book.dev
DocumentRoot /var/www/book
Alias /static/ /var/www/book/static
Alias /media/ /var/www/book/media
<Directory /var/www/book/static>
Order deny,allow
Allow from all
</Directory>
WSGIScriptAlias / /home/rich/sites/book/apache/django.wsgi
<Directory /home/rich/sites/book>
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
If I navigate to STATIC_ROOT in my web browser (in this case www.book.dev/static) I see a (correct) listing of the first level in the directory structure on the server. However, trying to follow the links to sub-directories, or even files in the root directory, yields only a 404. I'm using Django 1.3, Python 2.6, and some version of apache in the 2.X range (whatever is the most recent version in debian's package repo)
Any help is appreciated.
EDIT: (The plot thickens!)
So, after fiddling some more, I found something that I thought was interesting. I discovered that if I run the development server, the URL's from which static content is fetched are identical to the static file URL's which are generated when Apache is serving the files. This is to say, they all take the form /static/<file> as configured in settings.py, but sometimes it doesn't work.
Try having:
Alias /static/ /var/www/book/static/
Alias /media/ /var/www/book/media/
If using trailing slashes for a sub URL, the target file system path should have a trailing slash as well.
Compare to documentation at:
http://code.google.com/p/modwsgi/wiki/ConfigurationGuidelines#Hosting_Of_Static_Files
Please double check your settings.py. Look for commas and logic of directory structure. Especially about STATIC_ROOT and MEDIA ... dirs.
Problems are often not where they came from.
And you can create a symink to apache dir... and take it to where it was on your project at dev file structure... Try it may show your errors in templates if they exist...