Cannot load static files in production after trying numerous solutions - python

I have moved my django project from development to my production server. After deployment I cannot view static files on my pages.
I know that django does not serve static files once debug is turned off and have tried using whitenoise to serve my static files.
Attempt 1- WhiteNoise
These are the changes that I made to settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'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',
]
and wsgi.py:
from whitenoise.django import DjangoWhiteNoise
...
application = get_wsgi_application()
application = DjangoWhiteNoise(application)
and then running collectstatic. However my webpages still were not loading any of the static files.
Attempt 2- Apache- mod_wsgi
With the second attempt, I tried using apache+ mod_wsgi To be specific I connected to my VPS using terminal in cpanel installed apache2 and followed a tutorial.
sudo apt-get install apache2
created my conf file
sudo nano new_config.conf
added this to it
<VirtualHost *:80>
ServerName 127.0.0.1
ServerAlias localhost
Alias /static /var/gradientboostmvp/static/
WSGIScriptAlias / /var/gradientboostmvp/django_school/wsgi.py
<Directory /var/gradientboostmvp/>
Order deny,allow
Allow from all
</Directory>
DocumentRoot /var/gradientboostmvp
</VirtualHost>
enabled the newly created virtual host conf file
sudo a2ensite new_config.conf
sudo /etc/init.d/apache2 restart
added my WSGIPythonPath in apache2.config
WSGIPythonPath /var/gradientboostmvp
saved the changed, but still couldn't load my static files
Attempt 3- Import serve
I also had a similar question that was closed as a duplicate. I tried the solutions offered in the answers
from django.views.static import serve
...
urlpatterns = [
path('', classroom.home, name='home'),
path('about', classroom.about, name='about'),
path('courses', classroom.courses, name='courses'),
path('course_details', classroom.course_details, name='course_details'),
path('static',serve {'document_root':settings.STATIC_ROOT}),
Which then resulted in me getting an error message when I tried visiting my home page
Incomplete response received from application

Well, as you are using Apache to serve django, then why not use it serve static files as well. As per documetation, first you need to use collectstatic to store static files to a specific folder. For example in your settings if you have STATIC_ROOT specified as:
STATIC_ROOT = '/path/to/mysite.com/static/'
Then when you run collect static, the static files will be stored inside /path/to/mysite.com/static/ directory.
Then add that path as alias to apache:
Alias /static/ /path/to/mysite.com/static/

Related

Django - deployed, 403 for static but it should have permission, wsgi + Apache

my deployed Django project can't access the static files, I get 403 for all of them when inspecting in Chrome.
I added the following to my 000-default.conf where I also have the WSGIScriptAlias etc.:
Alias /static/ /home/budget/static/deploy/
<Directory /home/budget/static/deploy>
Required all granted
</Directory/
The static files exist in the budget/static/deploy folder. Should this not give the required permissions? What do I have to change to get rid of the 403?
It is running on Ubuntu 16.04.
Edit:
settings.py:
STATIC_URL = '/static/'
STATICFILES_DIRS = (
#os.path.join(BASE_DIR, 'budget/static'),
os.path.join(BASE_DIR, "static"),
)
STATIC_ROOT = os.path.join(BASE_DIR, "static/deploy/")
There may be a couple of different things that cause your configuration not to work. First of all, I would make sure that you are indeed modifying the proper Apache configuration file. You can run this command to check this:
/usr/sbin/apachectl -V | grep SERVER_CONFIG_FILE | awk '{split($0,a,"="); print a[2]}' | sed s/\"//g
Then, to delegate other API requests to django through WSGI, you should also give the correct permissions to your wsgi file (maybe this is not absolutely required for mere static serving to work):
<Directory /path/to/django/project/project>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
Next, set the process information to be used by Apache as well as your binding url for your project.
WSGIDaemonProcess myproject python-path=/path/to/django/project python-home=/path/to/your/venv
WSGIProcessGroup mydjangoproject
WSGIScriptAlias /binding/url /path/to/django/project/project/wsgi.py
Lastly, you may need to set up some permissions to allow www-data to read your media and static files and you should be all set. Don't forget to restart Apache to apply the modifications.

No module named urls / no response with django + mod_wsgi

I have a functioning Django application on the local development server, however when deyploying it to an Apache + mod_wsgi setup the urls don't seem to get resolved correctly, i.e. the url module within an installed app cannot be loaded. I have been debugging this for quite some time now and would greatly appreciate some help.
There is actually no real error message in the apache logs, so there might be some infinite loop going on, but I wouldn't know where or why. After a long time the request ends with error code 500 and log message: "Daemon process deadlock timer expired, stopping process 'Tianjin'." I found the url import to be the problem through painful debugging and print statements and realizing this is the point where the application gets stuck. The stack is something like this, where import(name) never returns with name being "Tianjin.urls".
import_module [__init__.py:37]
urlconf_module [urlresolvers.py:396]
url_patterns [urlresolvers.py:402]
resolve [urlresolvers.py:366]
get_response [base.py:119]
My setup:
Linux 4.2.0-27-generic #32-Ubuntu SMP x86_64 GNU/Linux
Apache/2.4.12 (Ubuntu) Server MPM: forked threaded
Python 2.7 in a virtual environment called env in the project folder
mod_wsgi-4.4.21, compiled from sources
Django 1.8.5
Directory structure in /home/TianjinAdmin/:
-IRIS
-env
-..
-Tianjin
- __init__.py
- celery.py
- settins.py
- urls.py
- wsgi.py
-TianjinUI
- __init__.py
- admin.py
- models.py
- tests.py
- urls.py
- views.py
-TianjinBE
- ...
- manage.py
Apache Virtual Host Configuration:
<VirtualHost *:80>
ServerAdmin bla#gmail.com
DocumentRoot /var/www/html
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
Alias /static /home/TianjinAdmin/IRIS/templates/TianjinUI/app
<Directory /home/TianjinAdmin/IRIS/templates/TianjinUI/app>
Require all granted
</Directory>
<Directory /home/TianjinAdmin/IRIS/Tianjin>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
WSGIDaemonProcess Tianjin python-path=/home/TianjinAdmin/IRIS:/home/TianjinAdmin/IRIS/env/lib/python2.7/site-packages processes=2 threads=15 display-name=%{GROUP}
WSGIProcessGroup Tianjin
WSGIScriptAlias / /home/TianjinAdmin/IRIS/Tianjin/wsgi.py
</VirtualHost>
Tianjin/wsgi.py
import os, sys
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Tianjin.settings")
#tried with and without the following two lines
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../")))
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../")))
print >> sys.stderr, sys.path
application = get_wsgi_application()
relevant Content of Tianjin/settings.py:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
#'kombu.transport.django',
'kombu.transport.django.KombuAppConfig',
'djcelery',
'TianjinBE',
'TianjinUI',
)
ROOT_URLCONF = 'Tianjin.urls'
Tianjin/urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^ui/', include('TianjinUI.urls')),
url(r'^oauth/', include('TianjinBE.urls')),
url(r'^admin/', include(admin.site.urls)),
]
Turns out, it had nothing to do with my configuration. Somewhere hidden in the logs and sometimes swallowed was the warning "Matplotlib is building the font cache using fc-list. This may take a moment.". So I had a 3rd party python library for matplot that blocked the application. Seemingly because of some permissions problem on caching files, see matplotlib taking time when being imported

Deploy Django Server on Apache+Ubuntu on a special port

I have done a simple Django Project for university.
Now I want to show it on my own hosted virtual server, like www.myserver.com:8001
I'm using Ubuntu 14.04 with apache2.
In /etc/apache/site-available I have a con file named: uniproject.conf
<VirtualHost *:8001>
DocumentRoot "/var/www/uniproject/"
Servername www.myserver.com:8001
Alias /static /var/www/uniproject/static/
WSGIScriptAlias / /var/www/uniproject/uniproject.wsgi
<Directory /var/www/uniproject/>
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
In /etc/apache2/ports.conf I wrote Listen 8001
In /var/www/uniproject/uniproject.wsgi
import os
import sys
sys.path = ['/var/www/uniproject'] + sys.path
os.environ['DJANGO_SETTINGS_MODULE'] = 'uniproject.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
After a2ensite uniproject.conf and service apache2 restart I'm calling www.myserver.com:8001
there comes
Not Found
The requested URL / was not found on this server.
My goal is to have, later on, about running three to five django apps/servers on my site reachable like
www.myserver.com:8001, www.myserver.com:8002, www.myserver.com:8003, etc ...
but what I do wrong?
I'm using Django 1.7.1 without virtualenv
The Apache Log says:
Target WSGI script not found or unable to stat: /var/www/uniproject, referer: http://www.myserver.com:8001/
The file structure in /var/www/uniproject is:
db3.sqlite
uniproject
uniprojectBackend
uniprojectwsgi
manage.py
static
templates
In /var/www/uniproject/uniproject are the default django files when creating a new project (setting.py, urls.py, wsgi.py, __init__.py)
drwxr-xr-x 7 root root 4096 Dec 21 21:50 uniproject
Ok here is how I solved my issue.
I'm now disabling the port stuff and use subdomain instead.
HOWTO: "Deploy various numbers of Django Apps on Apache2 running on Ubuntu 14.04"
First:
cd /etc/apache2/site-available
sudo nano someproject.conf
in someproject.conf:
<VirtualHost *:80>
ServerName someproject.mysite.com
ServerAlias www.someproject.myssite.com
DocumentRoot "/var/www/someproject/"
Alias /static /var/www/someproject/static/
WSGIScriptAlias / /var/www/someproject/wsgi.py
<Directory /var/www/someproject/>
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
after that run:
sudo a2ensite someproject.conf
sudo service apache2 restart
Second:
cd /var/www/
django-admin.py startproject someproject
cd someproject
sudo nano wsgi.py
in wsgi.py
import os
import sys
path = '/var/www/someproject'
if path not in sys.path:
sys.path.append(path)
os.environ['DJANGO_SETTINGS_MODULE'] = 'someproject.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
now visit: someproject.mysite.com
This is done with django 1.7.1
Make Sure all python modules are also installed (e.g. lxml, feed parser etc.)
Sometimes there will be a bug (happen to me) in settings.py
remove or comment in settings.py:
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
#'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
After every edit in the django project run
sudo service apache2 reload
Hope this helps anyone.
With this method I'm running three django server/apps on my VM.

404 Error while serving Django 1.7 static files on Apache

I've been a django developer for years now, yet a small practice project with 1.7 is giving me a great headache when it comes to serving static files.
I've set STATIC_ROOT
STATIC_ROOT = '/var/www/mydomain/static'
I've set STATIC_URL
STATIC_URL = '/static/' #as default
I'm not using STATICFILES_DIRS since I have one app called 'pages' and it's in INSTALLED_APPS. On localhost the static files are served correctly
I'm using Ubuntu 14.4 and Apache/2.4.7
My apache conf is
<VirtualHost *:80>
ServerName mydomain.net #I own the domain and pointed it correctly in GoDaddy
ServerAlias www.mydomain.net
Alias /static/ /var/www/mydomain/static
<Directory /var/www/mydomain/static>
Require all granted
</Directory>
WSGIScriptAlias / /var/www/mydomain/mydomain/wsgi.py
<Directory /var/www/mydomain/mydomain>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
WSGIDaemonProcess mydomain.net python-path=/var/www/mydomain:/var/www/mydomain/venv/lib/python2.7/site-packages
WSGIProcessGroup mydomain.net
</VirtualHost>
I've run collectstatic and confirmed all static files are in /var/www/mydomain/static/*.
The site loads, but I get a 404 on all css and js files.
All debugging efforts have failed. I've removed the STATIC_ROOT dir to expect a 403, but still getting a 404. I've chown'd all files/folder to root for testing; nothing. I created a deploy user and chown'd all files/folders to it; nothing. I've chown'd all files/folders to www-data; nothing!!
Is there a new config in Apache 2.4+ that's throwing me off?
What you can do is check your /var/www/mydomain path and look for the folder. I think its not there yet. If not then copy your folder to this place so that apache can serve it.
That will be worth looking

What is the most common way to configure static files in debug and production for Django

When developing a Django application in debug mode, I serve static files using the following code:
if settings.DEBUG:
urlpatterns += patterns('',
(r'^m/(?P<path>.*)$', serve, {
'document_root' : os.path.join(os.path.dirname(__file__), "media")
})
)
I am using nginx as a front end to server my static files in production mode using the following nginx config:
location m/
{
root /path/to/folder/media/;
}
Which seems sub-optimal because I have to create a "m" folder in the media directory. I am wondering what everyone else's Django/nginx config files look like. Specifically, can you please cut-and-paste sections of nginx.confg and urls.py (settings.DEBUG == True)
Thanks.
Using Django 1.3 django.contrib.staticfiles will take care of serving everything for you during development. You don't need to do anything particular in the urls.py. I wrote a little guide for myself after the Django 1.3 update that covers the settings to use:
# idiom to get path of project
import os
PROJECT_PATH = os.path.dirname(os.path.abspath(__file__))
# url prefix for user uploaded files, stuff that django has to serve directly
MEDIA_URL = '/media/'
# url prefix for static files like css, js, images
STATIC_URL = '/static/'
# url prefix for *static* /admin media
ADMIN_MEDIA_PREFIX = STATIC_URL + 'admin/'
# path to django-served media
MEDIA_ROOT = os.path.join(PROJECT_PATH, 'media')
# path used for collectstatic, *where the webserver not django will expect to find files*
STATIC_ROOT = '/home/user/public_html/static'
# path to directories containing static files for django project, apps, etc, css/js
STATICFILES_DIRS = (
os.path.join(PROJECT_PATH, 'static'),
)
# List of finder classes that know how to find static files in various locations.
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
# Required for all the magic
INSTALLED_APPS = (
'django.contrib.staticfiles',
)
Refer to the docs for details: http://docs.djangoproject.com/en/1.3/howto/static-files/.
I use nginx and uwsgi for serving django apps in production (I use runserver for development). I symlink my /static and /media folders (from my django project) into /var/www/vhosts/domain.com/html for nginx to find. You could also use the collectstatic command instead of symlinking. If it can't find a static file it falls back to uwsgi (which is running the django app).
Instead of uwsgi you could use fast-cgi, or proxy_pass or whatever you want. I prefer uwsgi because it has an incredible number of features and great performance. I run uwsgi as a daemon with: uwsgi --emperor '/srv/*/*.ini'. This is a fairly new option, it tells uwsgi to scan a given path for configuration files. When the emperor uwsgi daemon finds a configuration file it launches a new instance of uwsgi using the configuration found. If you change your configuration the emperor uwsgi daemon will notice and restart your app for you. You can also touch the config file to reload like with mod_wsgi, and it's really easy to setup new apps once you have everything configured initially.
The path conventions I follow are:
/srv/venv/ - virtualenv for project
/srv/venv/app.ini - configuration for uwsgi
/srv/venv/app.sock - uwsgi sock for django
/srv/venv/app.wsgi - wsgi file for uwsgi
/srv/venv/proj - django project
/srv/venv/proj/settings.py - project settings file
/srv/venv/proj/static - static files dir, linked into var/www/vhosts/domain.com/html
/srv/venv/proj/static/admin - admin static files, linked as well
/srv/venv/proj/media - media files dir
/var/www/vhosts/domain.com/html - base directory for nginx to serve static resources from
This is my nginx.conf:
location / {
root /var/www/vhosts/domain.com/html;
index index.html index.html;
error_page 404 403 = #uwsgi;
log_not_found off;
}
location #uwsgi {
internal;
include /etc/nginx/uwsgi_params;
uwsgi_pass unix:/srv/venv/app.sock;
}
My uwsgi ini file (you can also use xml/yaml/etc):
[uwsgi]
home = /srv/%n
pp = /srv/%n
wsgi-file = /srv/%n/%n.wsgi
socket = /srv/%n/%n.sock
single-intepreter = true
master = true
processes = 2
logto = /srv/%n/%n.log
You should also check out gunicorn, it has really nice django integration and good performance.
I'm putting this here in case someone wants an example of how to do this for Apache and WSGI. The question title is worded such that it's not just covering nginx.
Apache/WSGI Daemon
In my deployment, I decided to keep the database connection info out of the settings.py file. Instead I have a path /etc/django which contains the files with the database configuration. This is covered in some detail in an answer to another question. However, as a side effect, I can check for the presence of these files and the project being in a certain path to determine if this is running as a deployment, and in settings.py I define the settings IS_DEV, IS_BETA, and IS_PROD as True or False. Finding the project's directory from settings.py is just:
# Find where we live.
import os
BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
Anything that needs a path into the project uses BASE_DIR. So in urls.py, I have at the end:
# Only serve static media if in development (runserver) mode.
if settings.IS_DEV:
urlpatterns += patterns('',
url(r'^static/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT,
'show_indexes': True}),
)
(I also have another URL in there that I use for UI testing and don't want on beta or production.)
This covers the development server case. For production, I just have to set the Apache configuration up to serve the static stuff. (This is an intranet application with low to medium load, so I don't have a lightweight webserver like lighttpd to serve the static stuff, contrary to the Django docs' recommendation.) Since I'm using Fedora Core, I add a django.conf file in /etc/httpd/conf.d that reads similar to:
WSGIDaemonProcess djangoproject threads=15
WSGISocketPrefix /var/run/wsgi/wsgi
Alias /django/static/ /var/www/djangoproject/static/
Alias /django/admin/media/ /usr/lib/python2.6/site-packages/django/contrib/admin/media/
WSGIScriptAlias /django /var/www/djangoproject/django.wsgi
WSGIProcessGroup djangoproject
<Directory /var/www/djangoproject>
Order deny,allow
Allow from all
</Directory>
<Directory /usr/lib/python2.6/site-packages/django/contrib/admin/media>
Order deny,allow
Allow from all
</Directory>
IIRC, the key here is to put your Alias lines before your WSGIScriptAlias line. Also make sure that there's no way for the user to download your code; I did that by putting the static stuff in a static directory that is not in my Django project. That's why BASE_DIR gives the directory containing the Django project directory.
You can omit the WSGISocketPrefix line. I have it because the admin wants the sockets in a non-default location.
My WSGI file is at /var/www/djangoproject/django.wsgi (i.e. /django.wsgi in the Mercurial repository) and contains something like:
import os
import sys
os.environ['DJANGO_SETTINGS_MODULE'] = 'djangoproject.settings'
os.environ['DB_CONFIG'] = '/etc/django/db_regular.py'
thisDir = os.path.dirname(__file__)
sys.path.append(thisDir)
sys.path.append(os.path.join(thisDir, 'djangoproject'))
sys.path.append(os.path.join(thisDir, 'lib'))
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
The nice thing about WSGI daemons is that you just have to touch django.wsgi to restart your Django WSGI daemon; you don't need to reload or restart the Apache server. This makes the admin happy.
Finally, since my /var/www/djangoproject is just a Mercurial repo, I have the following in /var/www/djangoproject/.hg/hgrc:
[hooks]
changegroup.1=find . -name \*.py[co] -exec rm -f {} \;
changegroup.2=hg update
changegroup.3=chgrp -Rf djangoproject . || true
changegroup.4=chmod -Rf g+w,o-rwx . || true
changegroup.5=find . -type d -exec chmod -f g+xs {} \;
changegroup.6=touch django.wsgi # Reloads the app
This clears Python bytecode, updates the working copy, fixes up all the perms, and restarts the daemon whenever a developer pushes into deployment, so anyone in the djangoproject group can push into it and not just the last one who added a file. Needless to say, be careful who you put in the djangoproject group.
zeekay sets STATIC_URL, STATIC_ROOT, STATICFILES_DIRS, STATICFILES_FINDERS and uses "django.contrib.staticfiles" and "django.core.context_processors.static" in his settings. I don't have those since my code dates back to Django 1.1 and don't use {{ STATIC_ROOT }}.
Hope this helps.

Categories

Resources