Google App Engine + Django
Яким би поганим не здався мені на перший погляд Datastore у Google App Engine, але тим не менш для багатьох проектів і його буде цілком достатньо (тим паче, що у roadmap його розвитку майорить довгоочікуваний повнотекстовий пошук). Тому для платформи одного з нових міні-проектів, які нещодавно спали мені на думку мну вибрав саме Google App Engine. Водночас мну дуже вже звик до фреймворку Django і мається на увазі не лише його ORM, тому вирішив підключити його останню версію (в комплекті з GAE йде 0.96, яка вже ну дууууже застаріла). Але не за допомогою костилів (цього чи ось цього) як минулого разу, а просто напряму і викинувши все зайве (тобто фактично все, що було зав’язано на ORM). І не дивлячись на те, що в Інеті було повно мануалів по підключенню Django помучитись в неочікуваних місцях трохи довелося.
По-перше, сама збірка Django. Я підбирав модулі частково експериментальним шляхом і щоб не прописувати все вручну постійно зробив собі простенький .bat-файл, який пакує в архів необхідну частину джанги:
"C:\Program Files\7-Zip\7z.exe" a django.zip
^ django\__init__.py
^ django\bin
^ django\core
^ django\conf
^ django\db
^ django\dispatch
^ django\forms
^ django\http
^ django\middleware
^ django\shortcuts
^ django\template
^ django\template\tags
^ django\test
^ django\utils
^ django\views
^ django\contrib\__init__.py
^ django\contrib\contenttypes
^ django\contrib\localflavor
^ django\contrib\markup
^ django\contrib\sitemaps
^ django\contrib\humanize
^ django\contrib\formtools
Зібраний цим скриптом архівний файлик я підклав у корінь новоствореного gae-проекту. Причому пакування в архів тут робиться не задля економії дискового простору. Просто у App Engine є обмеження на кількість файлів, а в проекті Django їх дуже багато. Тепер залишилась справа за малим: підмінити Django що йде у комплекті з GAE на нашу версію, яку ми завантажимо з архіву за допомогою фічі zipimport. Тут все досить просто (це мій поточний варіант скрипта, але думаю без якихось проблем має запрацювати і той, що виклдаений на офіційній сторінці інтеграції GAE та Django):
#!/usr/bin/env python
# main.py
import os, sys, logging
os.environ["DJANGO_SETTINGS_MODULE"] = "projectname.settings"
# Google App Engine imports.
from google.appengine.ext.webapp
import util
# Uninstall Django 0.96.
for k in [k for k in sys.modules if k.startswith('django')]:
del sys.modules[k]
# Add Django 1.0 archive to the path.
django_path = 'django.zip'
sys.path.insert(0, django_path)
# Force Django to reload its settings.
from django.conf import settings
settings._target = None
import django.core.handlers.wsgi
import django.core.signals
import django.db
def log_exception(*args, **kwds):
logging.exception('Exception in request:') # Log errors.
django.core.signals.got_request_exception.connect(log_exception) # Unregister the rollback event handler.
django.core.signals.got_request_exception.disconnect(django.db._rollback_on_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()
Але найцікавіша частина над якою я намучився найбільше – це налаштування файлу settings.py в самому Django. По-перше, треба повідключати модулі зав’язані на Django ORM, тобто видалити або закоментити Middleware-класи:
django.contrib.sessions.middleware.SessionMiddleware
django.middleware.csrf.CsrfViewMiddleware
django.contrib.auth.middleware.AuthenticationMiddleware
django.contrib.messages.middleware.MessageMiddleware
**NOTE:**SessionMiddleware варто замінити на той, що йде у комплекті з gaeutilities – тоді ви принаймні зможете скористатись портованим аналогом сессій.
Контекст-процесори:
django.contrib.auth.context_processors.auth
django.contrib.messages.context_processors.messages
Та додатки:
django.contrib.auth
django.contrib.sessions
django.contrib.sites
django.contrib.messages
Також, наскільки я зрозумів, портована версія Django має певні проблеми з підтримкою i18n, тому в конфігураційному файлі її варто відключити (але питання інтернаціоналізації для мене вельми актуальне, тому найближчим часом постараюсь цю проблему вирішити):
USE_I18N = False
Ну от в принципі і все. Мну черпав джерело натхнення з: