We’ve heard it all. Appengine has uber scalability and that too on demand. And it is based on Django. Clarification – the python based SDK is based on django. And yes it is a great environment to develop in. No issues. But the thing that still causes me a bit of concern is the datastore. Oh it is fantastic, scalable and all that. But the limits are still limits. (I havent even mentioned the 1000 limit on blobs and files which is another big issue). And also my main concern is if I want to commit myself to writing all my code for appengine and then be in a position where porting to django would involve a total rewrite. Ok there are projects like appenginepatch and so on, but to me its trying to mold one paradigm into another. Why patch a key/value pair based datastore into an sql backend when each has their own strengths and you are better off writing interfaces that do it in specific ways so the same app at run time will choose the right implementation based on the environment rather than all the adapting of one paradigm to another?
So anyway, my M.O is to have a single project with the view and controller logic that is common for django and appengine but to have seperate model classes and APIs targetted to each backend. The models are accessed via the API classes that do all django/appengine specific magic behind the scenes transparent to the views and the controllers. I have talked more about this in a previous post. However I did not provide a specific implementation. This is now open sourced as part of the Djapps project. At the moment this is still in its infancy but it is a collection of app to do a lot of common tasks like external authentication, provide model accessors transparently based on appengine or django and so on. Still evolving and I will talk about this in future posts.
But to get started with all this, the first thing that needs to be worked on is settings.py. For better or worse, this file is where all your app specific settings go. So what I do is literally have a common_settings.py that i import from settings.py and have environment specific settings.py. So I include one depending on what kind of environment I am on. Environments for me would be “appengine dev server”, “appengine production server”, “local django server”, “production djanso server” etc.
So as an example, here is my settings.py. Very stripped down:
# -*- coding: utf-8 -*- import os import djapps # import all common settings - we will override them later on from djapps.default_settings import * # Make this unique, and don't share it with anybody. SECRET_KEY = 'xxxxx' # The root folder of the project PROJ_ROOT = os.path.abspath(os.path.split(__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. PROJ_ROOT + "/templates/" ) import dev_profiles # from dev_profiles.profile_dev_gae import * from dev_profiles.profile_prod_gae import * # from dev_profiles.profile_dev_nongae import * # from dev_profiles.profile_prod_nongae import * if not USING_APPENGINE: ROOT_URLCONF = 'myproject.urls'
Now in the above dev_profiles is the folder where all my different environment based settings files are (I call them profiles). So an example env specific settings py (profile_prod_gae from above) is:
URL_PATH_PREFIX = "" USING_APPENGINE = True SITE_URL = "http://myproject.appspot.com" SITE_NAME = "myproject" SERVE_STATIC = False USE_TEST_LOGIN = False DEBUG = True TEMPLATE_DEBUG = DEBUG PROJ_STATIC_HOST = "/static" DATABASE_ENGINE = '' DATABASE_NAME = 'myproject' DATABASE_USER = 'xxx DATABASE_PASSWORD = 'yyy' DATABASE_HOST = '' DATABASE_PORT = '' FORMAT_PARAM = "format" EMAIL_HOST = "localhost" EMAIL_PORT = 25 EMAIL_HOST_USER = "" EMAIL_HOST_PASSWORD = "" MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'djapps.gaeutils.middleware.SessionMiddleware', 'djapps.auth.local.middleware.LocalAuthMiddleware', 'djapps.auth.openid.middleware.OpenIDAuthMiddleware', # 'djapps.auth.external.middleware.MultiSiteAuthMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.middleware.doc.XViewMiddleware', ) TEMPLATE_CONTEXT_PROCESSORS = ( "djapps.utils.context_processors.site_urls", "djapps.utils.context_processors.gae_local_auth", "core.context_processors.openid_user", 'django.core.context_processors.request', "django.core.context_processors.debug", "django.core.context_processors.i18n", ) INSTALLED_APPS = ( 'djapps.utils', 'djapps.dynamo', 'djapps.auth.local', 'djapps.auth.external', 'djapps.events', 'profiles', )
Thats it. Nothing escapes customisation this way. In case y ou are wondering. The djapps.default_settings.py is just the settings.py that comes when you first create a django project (with startproject). Atleast it is very close.
Mind you this has served me very very well on past projects and has not required any major rewrites. One thing that does annoy me is the last line where I have to manually set the settings I have to choose (ie by uncommenting the line). You can get around this by checking for an environment variable and importing one based on that but again just a personal preference.
Let me know how this goes for you.