English ▼
Skip to page content Skip to main navigation
e.g. "templates" or "datastore"

# Running Django on Google App Engine

Damon Kohler
April 2008

WARNING (Nov 2010): This article is obsolete. The App Engine team is leaving it here for historical reasons; however, we recommend that you consider a project called Django-nonrel, a (currently) maintained fork of the latest version of Django which allows developers to run native Django applications (via Django's ORM) on traditional SQL databases as well as non-relational datastores (including App Engine's) without modification of your Django data model classes — you still need to work within App Engine's restrictions like no JOINs. For more information on using Django-nonrel with App Engine, please see our Django-nonrel article which shows you how to convert a native App Engine webapp app to a pure Django one.

## Introduction

Google App Engine and Django both have the ability to use the WSGI standard to run applications. As a result, it is possible to use nearly the entire Django stack on Google App Engine, including middleware. As a developer, the only necessary adjustment is modifying your Django data models to make use of the Google App Engine Datastore API to interface with the fast, scalable Google App Engine datastore. Since both Django and Google App Engine have a similar concept of models, as a Django developer, you can quickly adjust your application to use our datastore.

## Using Django 0.96.1

Google App Engine includes Django 0.96, so if you are on the latest stable release, there's nothing to install. Just import your Django modules as you would normally. We cover the modifications you will need to include if you are using the Django development version as well.

## Starting your Django Project

Assuming that the standard Django helper scripts are available in your path, you should be able to use django-admin.py to start a project in the root folder of your application.

    django-admin.py startproject project

This creates a subdirectory to host your Django apps as well as a placeholder settings.py. The files in this directory should look pretty familiar to an experienced Django developer. The next step will be to set up main.py to be able to launch the application.

## Writing your WSGI Handler in `main.py`

To get your Django application launched using the WSGI handler, it's just a few simple steps. Import `util` from `google.appengine.ext.webapp`, and the WSGI handler module from Django. Also, instead of handling exceptions using `manage.py`, we can log all exceptions with Google App Engine, and the logs will be viewable in the Admin console. For more information on logging with Google App Engine, you can read our article here.

    import logging, os

    # Google App Engine imports.
    from google.appengine.ext.webapp import util

    # Force Django to reload its settings.
    from django.conf import settings
    settings._target = None

    # Must set this env var before importing any part of Django
    # 'project' is the name of the project created with django-admin.py
    os.environ['DJANGO_SETTINGS_MODULE'] = 'project.settings'

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

    def log_exception(*args, **kwds):
        logging.exception('Exception in request:')

    # Log errors.
    django.dispatch.dispatcher.connect(
        log_exception, django.core.signals.got_request_exception)

    # Unregister the rollback event handler.
    django.dispatch.dispatcher.disconnect(
        django.db._rollback_on_exception,
        django.core.signals.got_request_exception)

    def main():
        # Create a Django application for WSGI.
        application = django.core.handlers.wsgi.WSGIHandler()

        # Run the WSGI CGI handler with that application.
        util.run_wsgi_app(application)

    if __name__ == '__main__':
        main()

Additionally, the `app.yaml` file for your Google App Engine application should look like this:

    application: my_application
    version: 1
    runtime: python
    api_version: 1

    handlers:
    - url: /static
      static_dir: static

    - url: /.*
      script: main.py

You can store the CSS, images, and other static content in your static directory.

## Installing Django Development Version

To use the development version, download the entire Django project, and include it in your application's top level directory. To reduce the number of files you deploy to Google App Engine, you can remove the following directories in your Django folder:

    django/bin
    django/contrib/admin
    django/contrib/auth
    django/contrib/databrowse
    django/test

You will need to modify your main.py to remove the standard version of Django and load the copy you included with your application:

    import logging, os, sys

    # Google App Engine imports.
    from google.appengine.ext.webapp import util

    # Remove the standard version of Django.
    for k in [k for k in sys.modules if k.startswith('django')]:
        del sys.modules[k]

    # Force sys.path to have our own directory first, in case we want to import
    # from it.
    sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))

    # Must set this env var *before* importing any part of Django
    os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

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

    def log_exception(*args, **kwds):
       logging.exception('Exception in request:')

    # Log errors.
    django.dispatch.dispatcher.connect(
        log_exception, django.core.signals.got_request_exception)

    # Unregister the rollback event handler.
    django.dispatch.dispatcher.disconnect(
        django.db._rollback_on_exception,
        django.core.signals.got_request_exception)

    def main():
        # Create a Django application for WSGI.
        application = django.core.handlers.wsgi.WSGIHandler()

        # Run the WSGI CGI handler with that application.
        util.run_wsgi_app(application)

    if __name__ == '__main__':
        main()

## Updating Django Settings

Since App Engine does not support Django models, leave all DATABASE_* settings set to an empty string. The authentication and admin middleware and apps should be disabled since they require Django models. The functionality these provide is covered by the App Engine Users API and Admin Console respectively. Sessions also depend on Django models and must be disabled as well. Finally, you need to set the path to your template directory dynamically.

    import os

    # 'project' refers to the name of the module created with django-admin.py
    ROOT_URLCONF = 'project.urls'

    MIDDLEWARE_CLASSES = (
        'django.middleware.common.CommonMiddleware',
    #    'django.contrib.sessions.middleware.SessionMiddleware',
    #    'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.middleware.doc.XViewMiddleware',
    )

    INSTALLED_APPS = (
    #    'django.contrib.auth',
        'django.contrib.contenttypes',
    #    'django.contrib.sessions',
        'django.contrib.sites',
    )

    ROOT_PATH = os.path.dirname(__file__)
    TEMPLATE_DIRS = (
        # Put strings here, like "/home/html/django_templates" or
        # "C:/www/django/templates".  Always use forward slashes, even on Windows.
        # Don't forget to use absolute paths, not relative paths.
        ROOT_PATH + '/templates',
    )

## Using the Development Environment

At this point, you should be able to use `dev_appserver.py` to launch the application. If everything has gone well, when you point your browser to http://localhost:8080, you should see Django's "It worked!" page. Since you will be using the App Engine datastore, there is no need to use `manage.py` to sync the database.

## Conclusion

That's it! You can now build your application as you normally would using Django.