Serving static files on Apache with Django (404 error) - python

I've been trying to setup an Apache (2.2.15) as a proxy with gunicorn and django (1.6.11) on a CentOS server (6.7), but I'm stuck on a problem regarding the static files. (I'm fairly new to django)
I have already looked at the great documentation that Django provides, as well as a few other stackoverflow's posts, but to no avail.
What I could check :
The problem doesn't seem to come from Django or the templates, as running the development server with 'DEBUG = False' and the option '--insecure' works fine.
It probably is a problem with the Alias and Directory block I added in my virtualhost, but I can't make sense of why it doesn't work.
Gunicorn shouldn't have any word to say in it, as it doesn't serve static files.
What my configuration looks like :
1) I got my project's static files into '/var/www/myproject/static' thanks to the 'collectstatic' command.
2) Then, I created the virtualhosts (where I think the problem is) :
(first one for the redirection to HTTPS)
<virtualhost *:80>
ServerAdmin user#domain.com
ServerName localhost
ServerSignature Off
RewriteEngine on
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [NC,R,L]
</virtualhost>
(second one for the actual work)
<virtualhost *:443>
ServerAdmin user#domain.com
ServerName localhost
ServerSignature Off
DocumentRoot /var/www/myproject
Alias /static/ "/var/www/myproject/static/"
<Directory "/var/www/myproject/static">
Order Allow,Deny
Allow from All
</Directory>
ProxyPass / http://127.0.0.1:8000/ connectiontimeout=150 timeout=300
ProxyPassReverse / http://127.0.0.1:8000/
ProxyPreserveHost On
ProxySet http://127.0.0.1:8000/ connectiontimeout=150 timeout=300
... here goes the SSL and Log configuration ...
</virtualhost>
After a service restart, my static files weren't loaded and I had a 404 error on their get. An 'httpd -S' didn't throw any error and the rest of the functionalities of the web interface are working great.
I also tried without the ending '/' for the '/static/' alias as it seemed to be a problem for some other people, tried to move the files directly under /var/www/myproject and have them accessed without an alias with the DocumentRoot...
If you want to have a look at the django settings.py (don't know if it's relevant, but some django guru could find something wrong there too) :
STATIC_ROOT = '/var/www/myproject/static/'
STATIC_URL = '/static/'
STATICFILES_DIRS = (os.path.join(os.path.dirname(__file__),'static',),)
As well as the templates :
{% load staticfiles %}
....
<link href="{% static 'bower_components/bootstrap/dist/css/boostrap.min.css %}" rel="stylesheet">
Urls.py of the project :
from django.conf.urls import patterns, include, url
from django.shortcuts import redirect
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = patterns('',
url(r'^$', lambda x: redirect('/Collecte/')),
url(r'^Collecte/', include('Collecte.urls', namespace="Collecte")),
) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
And the urls.py of the app (named 'Collecte'):
from django.conf.urls import patterns, url
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from Collecte import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^Collectes/Execution/รน', views.CollExecution, name='CollExecution'),
... quite a lot of them ...
)
# Commented this line from a suggestion, was present at start
#urlpatterns += staticfiles_urlpatterns
If you feel like any file is missing for the question to be relevant, just ask for it and I'll do my best :).

Alright,
I found the answer to my question in another stackoverflow thread that had a similar configuration (but with flask instead of django).
As Ajay Gupta said, I think I had a problem in the urls.py file of the project as I had to add 'static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)' (switched from using the staticfiles app django provides to this other way).
The other problem was in the apache virtualhost configuration, as I wanted my static files to be served by apache and not gunicorn or django. I was redirecting everything to the gunicorn server, even the requests to static files. So I had to add 'ProxyPass /static/ !' so that apache serves the files.
I don't know if it's the right way to do it, but it worked for me.

from django.contrib.staticfiles.urls import staticfiles_urlpatterns
is a helper function that works only when
debug = True
So for instance just set debug = True again, restart your server and check

Related

Pop-ups in django-tinymce editor showing 404 error

What is wrong:
I have installed django-tinymce to work with text fields in the admin section of my site. The editor works good, though not as expected, because whenever I try to insert an image, link, symbol etc. - that is, whenever a pop-up is ensued - editor opens a 404 Not found window instead of actual widget form.
What I have tried:
I 've tried adding
document.domain = 'my_site.com';
to tiny_mce_popup.js. Nothing changed.
Interestingly enough, the *.htm files, which are supposed to open in pop-up windows, are stored in the directory {{ MEDIA_URL }}js/tiny_mce/themes/advanced/ (as I've mentioned, server doesn't open them). But if I try and open in browser other files from that very same directory (e.g. {{ MEDIA_URL }}js/tiny_mce/themes/advanced/editor_template.js or {{ MEDIA_URL }}js/tiny_mce/themes/advanced/img/flash.gif), everything works - the files are displayed without any error.
In addition, on local server everything works just fine - the problem is encountered only after deployment.
Code that might help identifying the problem:
Project's urls.py:
urlpatterns = patterns('',
#...
url(r'^tinymce/', include('tinymce.urls')),
#...
)
TinyMCE's urls.py:
from django.conf.urls.defaults import *
urlpatterns = patterns('tinymce.views',
url(r'^js/textareas/(?P<name>.+)/$', 'textareas_js', name='tinymce-js'),
url(r'^js/textareas/(?P<name>.+)/(?P<lang>.*)$', 'textareas_js', name='tinymce-js-lang'),
url(r'^spellchecker/$', 'spell_check'),
url(r'^flatpages_link_list/$', 'flatpages_link_list'),
url(r'^compressor/$', 'compressor', name='tinymce-compressor'),
url(r'^filebrowser/$', 'filebrowser', name='tinymce-filebrowser'),
url(r'^preview/(?P<name>.+)/$', 'preview', name='tinymce-preview'),
)
TinyMCE's settings.py:
import os
from django.conf import settings
DEFAULT_CONFIG = getattr(settings, 'TINYMCE_DEFAULT_CONFIG',
{'theme': "advanced", 'relative_urls': False})
USE_SPELLCHECKER = getattr(settings, 'TINYMCE_SPELLCHECKER', False)
USE_COMPRESSOR = getattr(settings, 'TINYMCE_COMPRESSOR', False)
USE_FILEBROWSER = getattr(settings, 'TINYMCE_FILEBROWSER',
'filebrowser' in settings.INSTALLED_APPS)
JS_URL = getattr(settings, 'TINYMCE_JS_URL',
'%sjs/tiny_mce/tiny_mce.js' % settings.MEDIA_URL)
JS_ROOT = getattr(settings, 'TINYMCE_JS_ROOT',
os.path.join(settings.MEDIA_ROOT, 'js/tiny_mce'))
JS_BASE_URL = JS_URL[:JS_URL.rfind('/')]
So how do I make django-tinymce's pop-ups work? Thanks in advance for your help!
EDIT: Solution found. Turns out my hosting provider didn't include htm(l) in allowed static files extensions list. Now everything's working.
The fact that it is working under the development server, but not live, leads me to think that you haven't set up the media root properly in your apache conf. The development server automatically serves your media and static files but for your live deployment you need to add the media and static aliases with the relevant path.
vhost.conf:
<VirtualHost *:80>
# Your setup for your main site url, then add the below to allow access
# to the media and static roots
Alias /media/ "/path/to/myproject/media/"
<Directory "/path/to/myproject/media/">
Order deny,allow
Allow from all
</Directory>
Alias /static/ "/path/to/myproject/static/"
<Directory "/path/to/myproject/static/">
Order deny,allow
Allow from all
</Directory>
</VirtualHost>

How to serve admin static files with django.contrib.staticfiles in Django 1.4 (using one Apache server)?

Django is recommending me that if I am going to only use one server (Apache) to serve both dynamic and static files, then I should serve static files using django.contrib.staticfiles.
So in my settings.py I have loaded django.contrib.staticfiles to my INSTALLED_APPS and django.core.context_processors.static to my TEMPLATE_CONTEXT_PROCESSORS.
I noticed in the admin templates that it links to static files like this (from index.html):
{% load i18n admin_static %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/dashboard.css" %}" />{% endblock %}
But looking at the template tag admin_static, it's simply a wrapper for static:
from django.conf import settings
from django.template import Library
register = Library()
if 'django.contrib.staticfiles' in settings.INSTALLED_APPS:
from django.contrib.staticfiles.templatetags.staticfiles import static
else:
from django.templatetags.static import static
static = register.simple_tag(static)
So I concluded that because every admin static file is serverd with a admin/... prefix, then the full path (for my case) should be
/usr/lib64/python2.7/site-packages/django/contrib/admin/static
So I set that path to my STATICFILES_DIRS inside settings.py, but Apache still won't serve any static files (after restating the server). Where did I make a mistake in my logic?
Thanks Daniel Roseman for the explanation and giving me the chance to learn it on my own (and now I won't forget!) :-).
Initially I was really confused and I didn't know you had to first collect the static files, then tell Apache to serve it. I thought simply using STATICFILES_DIRS and including the static app in settings.py was good enough.
So here is how I did it (and please let me know if I could have done it better):
In settings.py
STATIC_ROOT = '/var/www/localhost/htdocs/mysite/static/'
STATIC_URL = '/static/' # default
It seems Django already know where to collect the admin files, you don't need to specify anything in STATICFILES_DIRS unless you need to serve your own custom files (which I don't and thus I had no prior experience with static files in Django).
Then at /var/www/localhost/htdocs/mysite/ type python manage.py collectstatic -l. The -l means to create a symbolic link to all found static files instead of copying it over (saves some space).
Next edit the Apache config file (usually httpd.conf) and add the STATIC_URL information. My config file just for Django looks like this:
Alias /static/ /var/www/localhost/htdocs/mysite/static/
#In the form of...
#Alias STATIC_URL STATIC_ROOT
<Directory /var/www/localhost/htdocs/mysite/static>
Order deny,allow
Allow from all
</Directory>
WSGIScriptAlias / /var/www/localhost/htdocs/mysite/mysite/wsgi.py
WSGIPythonPath /var/www/localhost/htdocs/mysite
<Directory /var/www/localhost/htdocs/mysite/mysite>
<Files wsgi.py>
Order deny,allow
Allow from all
</Files>
</Directory>
Then restart Apache and done!
The documentation you link to doesn't say anything at all about serving files with the staticfiles app. That's not what it's for: it's for collecting staticfiles into a single place to allow them to be easily served by Apache. (It does deal with serving files in development, but that's not what we're talking about here.)
You still need to set up Apache to serve the files from the relevant location via the static/ prefix.

Redirecting Django root to admin panel

I'm trying to redirect the Django site root to the Django admin panel, and I've mostly got it up and running. However, I've noticed that unless there's a trailing slash in the project URL, the links on the page don't include the project folder, and instead try to find the apps in the site root.
So, say I've got a project foo, and an app bar. If you visit http://server/foo/ (with a trailing slash), everything works fine, and the links on the page go to http://server/foo/bar. However, if one visits http://server/foo, the generated links go to http://server/bar instead, which generates a 404 error.
If I set the WSGIScriptAlias to point to /foo/ instead of /foo, it would give a 404 error if I navigated to /foo. I tried to force a trailing slash in the Apache conf with Redirect, but I end up generating a recursive redirect (http://server/foo//////...). I haven't yet tried using a .htaccess file, but I suspect the same thing might happen.
I tried the same thing in urls.py, however:
url(r'^$', redirect_to, {'url': '/'}), # goes to server root http://server/
url(r'^$', redirect_to, {'url': 'foo/'}), # goes to http://server/foo/foo
url(r'^$', redirect_to, {'url': '/foo/'}), # infinite redirect
I also tried simply appending a slash to all the Django urls like so:
url(r'^(.*)/', include(admin.site.urls))
But it fails to match anything at all in the project root folder (although if you navigate to the app, that seems to work OK).
I'm using Apache 2.2 with mod_wsgi, here is the configuration:
Alias /static "C:/DJANGO~1/apps/django/django/contrib"
<Directory 'C:/DJANGO~1/apps/django/django/contrib'>
Order allow,deny
Allow from all
</Directory>
WSGIScriptAlias /foo "C:/Djangostack/apps/django/scripts/django.wsgi"
<Directory 'C:/Djangostack/apps/django/scripts'>
Order allow,deny
Allow from all
</Directory>
And this is the urls.py that mostly works:
urlpatterns = patterns('',
url(r'^', include(admin.site.urls)),
)
I've made sure APPEND_SLASH is set to True, but it doesn't seem to work in the root project folder.
Try setting APPEND_SLASH to True in your settings.py. I had a similar problem and this fixed it for me. It's supposed to default to True but I had to set it explicitly.

Django-modpython deploying project

I am deploying a Django project on apache server with mod_python in linux. I have created a directory structure like:
/var/www/html/django/demoInstall where demoInstall is my project. In the httpd.conf I have put the following code.
<Location "/django/demoInstall">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE demoInstall.settings
PythonOption django.root django/demoInstall
PythonDebug On
PythonPath "['/var/www/html/django'] + sys.path"
</Location>
It is getting me the django environment but the issue is that the urls mentioned in urls.py are not working correctly.
In my url file I have mentioned the url like:
(r'^$', views.index),
Now, in the browser I am putting the url like : http://domainname/django/demoInstall/ and I am expecting the views.index to be invoked. But I guess it is expecting the url to be only: http://domainname/ .
When I change the url mapping to:
(r'^django/demoInstall$', views.index),
it works fine. Please suggest as I do not want to change all the mappings in url config file.
Thanks in advance.
There's a fairly simple way around this using just django, without having to touch apache.
Rename your urls.py to something else, e.g. site_urls.py
Then create a new urls.py which includes that
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^django/demoInstall/', include('site_urls.py')),
)
This will ensure that all the url reversing continues to work, too.
That should be:
PythonOption django.root /django/demoInstall
Ie., must match sub URL in Location directive.
You shouldn't be using that prefix in urls.py.

Django Admin: not seeing any app (permission problem?)

I have a site with Django running some custom apps. I was not using the Django ORM, just the view and templates but now I need to store some info so I created some models in one app and enabled the Admin.
The problem is when I log in the Admin it just says "You don't have permission to edit anything", not even the Auth app shows in the page. I'm using the same user created with syncdb as a superuser.
In the same server I have another site that is using the Admin just fine.
Using Django 1.1.0 with Apache/2.2.10 mod_python/3.3.1 Python/2.5.2, with psql (PostgreSQL) 8.1.11 all in Gentoo Linux 2.6.23
Any ideas where I can find a solution?
Thanks a lot.
UPDATE: It works from the development server. I bet this has something to do with some filesystem permission but I just can't find it.
UPDATE2: vhost configuration file:
<Location />
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE gpx.settings
PythonDebug On
PythonPath "['/var/django'] + sys.path"
</Location>
UPDATE 3: more info
/var/django/gpx/init.py exists and is empty
I run python manage.py from /var/django/gpx directory
The site is GPX, one of the apps is contable and lives in /var/django/gpx/contable
the user apache is webdev group and all these directories and files belong to that group and have rw permission
UPDATE 4: confirmed that the settings file is the same for apache and runserver (renamed it and both broke)
UPDATE 5: /var/django/gpx/contable/init.py exists
This is the relevan part of urls.py:
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
)
urlpatterns += patterns('gpx',
(r'^$', 'menues.views.index'),
(r'^adm/$', 'menues.views.admIndex'),
Hopefully this helps someone, but we had this same problem because someone added a different authentication backend to settings.py and did not keep the default ModelBackend. Changing the setting to:
AUTHENTICATION_BACKENDS = (
'auth.authentication.EmailBackend',
'django.contrib.auth.backends.ModelBackend',
)
fixed it for us.
It sounds like you haven't registered any apps with the admin (step 5 in this overview).
Try adding the line admin.autodiscover() to your main urls.py, making sure to do from django.contrib import admin first.
For example:
# Other imports...
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
('^admin/', include(admin.site.urls)),
# Other URL patterns...
)
You can also register your models individually with admin.site.register(YourModel).
Try accessing your database and in the table auth_user make sure that the fiels is_staff, is_active and is_superuser are marked as true (1) for your user.
Make sure you have added your application to settings.INSTALLED_APPS.
The django template for the admin app index page reads:
{% if app_list %}
{% for app in app_list %}
...
{% else %}
<p>{% trans "You don't have permission to edit anything." %}</p>
{% endif %}
That must be your problem.
EDIT: Either that or you are not logged in as the user you say you are. Can you look in the database and make sure that the auth_user.is_superuser for the user in question has a value of 1?
EDIT: If you user is_staff and is_superuser are marked as 1 in the DB, and you are sure you are logged in as that user; is it possible that you are only seeing this in production (i.e. under apache) and that your settings.py for production is different than in development?
EDIT: So you have different behavior in dev and production. I can think of two scenarios:
a) You have a different settings.py for production. Can you edit your question showing the relevant portion of your httpd.conf? It should be something like:
<Location "/mysite/">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonOption django.root /mysite
PythonDebug On
</Location>
Also, what is your PYTHONPATH?
What is the SetEnv line saying? Is it pointing to the very same module you have in development? Are you sure in your PYTHONPATH you have mysite.settings as the file you think you have?
b) You have a PYTHONPATH problem in production and the apps can't be found. This should generate a much more severe error though...
Questions:
/var/django/gpx has a init.py correct?
/var/django/gpx/settings.py is the same file used as when you do manage.py runserver?
What is the name of your app at /var/django/?
Does the user your are running Apache under has permissions to all these directories?
We encountered the same problem when installing django 1.1 over an old installation of django 0.96
it was solved when we made a fresh install

Categories

Resources