Thursday, November 11, 2010

Running Django on Google App Engine

It took about five hours but I did it!!!

Google has this simple tutorial on how to start first Django project on GAE. It's helpful but not enough to debug all the errors novices run into. Here's the step by step instructions for someone familiar with basic Django.

1. Create the GAE app. 

Let's call it gaeapp.

I use GUI to provide app name and it creates a directory with following files.
app.yaml
index.yaml
main.py

2. Create the django project INSIDE the GAE app directory.
If you have created a Django project before, you would know to do so using

django-admin.py startproject djprj

Now we have a directory called djprj with following files.
__init__.py
manage.py
settings.py
urls.py

3. OPTIONAL
If you want, you can copy all the django files to GAE dir. Make sure to remove all refrences to Django project name. e.g. djprj.settings would become settings.

4. Edit app.yaml
I followed the instructions on the google's tutorial and kept getting error message - "unknown URL handler type". Turns out the code was not indented properly. 

"ERROR    2010-11-11 06:42:51,957 dev_appserver_main.py:407] Fatal error when loading application configuration:

while scanning a simple key
  in "~/gaeapp/app.yaml", line 8, column 1
could not found expected ':'"

Received above error since static_dir: and static were not separated by space. 

So this is how my appl.yaml looks
application: gaeapp
version: 1
runtime: python
api_version: 1

handlers:
- url: /static
  static_dir: static
- url: .*
  script: main.py

5. Edit main.py
Here's how my main.py looks. Note that if both django and GAE files are in the same folder, you should point DJANGO_SETTINGS_MODULE to the current directory and omit the Django project name unlike the google tutorial.

I kept getting message about DJANGO_SETTINGS_MODULE is not defined and then it disappeared. 

import os, logging
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util

from django.conf import settings
settings._target=None
os.environ['DJANGO_SETTINGS_MODULE']='djprj.settings'

import django.core.handlers.wsgi
import django.core.signals
import django.db
import django.dispatch.dispatcher

#class MainHandler(webapp.RequestHandler):
#    def get(self):
#        self.response.out.write('Hello World!')

def main():
    #application = webapp.WSGIApplication([('/', MainHandler)], debug=True)
    application=django.core.handlers.wsgi.WSGIHandler()
    util.run_wsgi_app(application)

if __name__ == '__main__':
    main()

6. Edit settings.py
  1. Comment out all of the middleware parameter else you might get this error "AttributeError: 'module' object has no attribute 'messages'".
  2. Ensure ROOT_URLCONF = 'urls' if  Django files are in GAE dir. Else it will be djprj.urls since our project is called djprj.

7. Done! 
Run the GAE app and the corn blue awaits you.

8. Doing the work - adding code
Standard Django practice is to have code in views.py. So let's 
create a views.py in Django dir. This will contain some code for first Django GAE app. This is what I've got -

from django.http import HttpResponse

def sayhello(request):
    return HttpResponse("This is my first GAE app using Django")

9. Edit urls.py
The standard process of including  code in django url.

from django.conf.urls.defaults import *
from djprj.views import *

from django.conf.urls.defaults import *
from djprj.views import *

urlpatterns = patterns('',
    ('',sayhello),
)

10. Refresh your page or restart your GAE app.

No comments: