Php – How to Django/WSGI and PHP share / on Apache

apache-2.2djangomod-phpPHPwsgi

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.

Best Answer

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.