Jérôme Belleman
Home  •  Tools  •  Posts  •  Talks  •  Travels  •  Graphics  •  About Me

Django with CERN Web Services

31 May 2012

Is it at all possible to set up Django for an AFS web site with CERN Web Services? Yes it is. The next question – how? – is what this posts aims at answering.

If putting together a dynamic web site with PHP is easy, the same cannot be said of Python; while you can easily inject PHP code into HTML, that's something you can't normally do with Python, where the custom is more to use web frameworks and templates to generate complete pages.

Setting up a web framework in a web server where you don't have total access, as is the case with shared-hosting providers such as the CERN Web Services, generally means you have to fly blind until you reach your goal in having a working setup. I guess you can see this recipe as a flight plan.

Note that what follows applies for so-called AFS folder web sites. I seem to remember I've done something similar for web sites Centrally hosted on DFS but the approach is different.

1 Setting up a Django Project in Your Box

Loosely following the Django tutorial you need to:

  1. Create a project with e.g. django-admin.py startproject foo.
  2. Create an application with e.g. python manage.py startapp website.
  3. Add the application to the project by adding 'website' to INSTALLED_APP in settings.py.
  4. Edit URLs in urls.py. The first example is actually a good inspiration and you may want to use something along the lines of url(r'^.*$', 'website.views.home', name='home'). You may also want to have any URLs call the same function to start with.
  5. Write the corresponding views to website/views.py:

    from django.http import HttpResponse
    
    def home(request):
        return HttpResponse("Hullo")
  6. I haven't seen it explicitly advised, but it may be wise to turn DEBUG = False in settings.py for security reasons.
  7. Try the project by running python manage.py runserver and browsing http://127.0.0.1:8000.

2 Deploying Your Web App on AFS via LXPLUS

  1. Since we can't seem to be able to run runfastcgi() with Python 2.6, better use Python 2.4. Get Django and flup.

    Technically, you need to make the destination directory read-accessible by the web server (fs sa -dir python -acl webserver:afs read). You might want to think about the security implications, though.

    After doing an export PYTHONPATH=~/python/lib/python2.4/site-packages you need to fire up python setup.py install --prefix ~/python for both.
  2. Copy your Django project somewhere outside ~/www (security), e.g. ~/projects which, technically, should also be read-accessible by the web server (again, fs sa -dir projects -acl webserver:afs read once you've pondered the security consequences).
  3. In the e.g. ~/www directory which, technically, would need to be read-accessible by the web server (fs sa -dir www -acl webserver:afs read – again, think about security), create an .htaccess file containing the following:

    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ cgi-bin/foo.fcgi/$1 [QSA,L]
    Note that you should omit AddHandler fastcgi-script .fcgi, otherwise the request will hang forever, for some reason. Also note that we're going to dump the fcgi file into cgi-bin, just for convenience because scripts this directory are allowed to be executed by default, although you can set up other directories for this purpose in https://webservices.cern.ch.
  4. Create an executable ~/www/cgi-bin/foo.fcgi file with the following lines:

    #! /usr/bin/env python
    
    import sys, os
    
    sys.path.insert(0, "../../python/lib/python2.4/site-packages")
    sys.path.insert(0, "../../projects/foo")
    sys.path.insert(0, "../../projects")
    
    os.environ['DJANGO_SETTINGS_MODULE'] = "foo.settings"
    
    from django.core.servers.fastcgi import runfastcgi
    runfastcgi(method="threaded", daemonize="false")

    Note that in this case the script is run from ~/cgi-bin. I haven't found changing directory to be useful. It also turns out that different parts of Django import packages from different locations, hence the need to specify the two projects and projects/foo paths.

3 References