2

I have a server running an established PHP site, as well as some Django apps.

Currently, a VirtualHost set up for PHP listens on port 80, and requests to certain directories are proxied to a VirtualHost set up for Django with WSGI.

I'd like to change it so Django handles anything not existing as a PHP script or static file.

For example,

/ ->parsed by PHP as index.php
/page.php ->parsed as PHP normally
/images/border.jpg ->served as a static file
/johnfreep ->handled by Django (interpreted by urls.py)
/pages/john ->handled by Django
/(anything else) - > handled by Django

I have a few ideas. It seems the options are 'php first' or 'wsgi first'.

  • set up Django on port 80, and set Apache to skip all the known PHP, CSS or image files. Maybe using SetHandler? Anything else goes to Django to be parsed by urls.py.

  • Set up a script referring everything to Django as a 404 handler on PHP. So, if a file is not found for a name, it sends the request path to a VirtualHost running Django to be parsed.

2
  • Is /johnfreep and /pages/john the same Django instance as /(anything else)? Jan 25, 2011 at 2:40
  • @Graham yes, that's right! Just one Django instance. I don't know why I listed that one differently, I'll edit for clarity. Jan 25, 2011 at 3:12

1 Answer 1

4

Use method described in:

http://code.google.com/p/modwsgi/wiki/ConfigurationGuidelines#The_Apache_Alias_Directive

Thus have DocumentRoot setup as normal for static files and php files etc. Then add:

AddHandler wsgi-script .wsgi

to Directory block for DocumentRoot, or globally for server.

You will though need to have:

Options ExecCGI

enabled for DocumentRoot now if you don't already.

Then also add:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /site.wsgi/$1 [QSA,PT,L]

where site.wsgi is in DocumentRoot and is the WSGI script file which maps to your Django application.

In Django WSGI script file change it to use:

import django.core.handlers.wsgi

_application = django.core.handlers.wsgi.WSGIHandler()

import posixpath

def application(environ, start_response):
    # Wrapper to set SCRIPT_NAME to actual mount point.
    environ['SCRIPT_NAME'] = posixpath.dirname(environ['SCRIPT_NAME'])
    if environ['SCRIPT_NAME'] == '/':
        environ['SCRIPT_NAME'] = ''
    return _application(environ, start_response)

That should be it.

Any request that maps to an actual file based resource under DocumentRoot, be it static file or php file, including as setup by DirectoryIndex, eg., index.php, will be handled normally. Any other URL which would otherwise result in 404, will instead be routed into the Django application.

The /johnfreep and /pages/john would have to have corresponding URL as if mounted at root, in the urls.py file.

If Django doesn't know what to do with a URL, then Django will return 404.

Read the wiki document for more information.

4
  • Thanks for the complete answer! That's just what I needed. Jan 25, 2011 at 3:39
  • I'll add a note for anyone else trying this: it was giving 403 Forbidden for every single URL (and thus driving me nuts as the rewrite seemed to be correct) until I added Options +FollowSymLinks. Jan 25, 2011 at 7:32
  • Yeah, forgot about that. RewriteRule is forbidden unless one of FollowSymLinks or SymLinksIfOwnerMatch options is set. Don't really understand the reasoning for that requirement. Jan 25, 2011 at 8:11
  • Oddly, I have other rewrite rules that seemed to be working. This one triggered an error message saying that about FollowSymLinks though, which I saw when I finally had the bright idea to check the error logs. Jan 25, 2011 at 10:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .