!!!Google App Engine で Djangoを利用する [Google App Engine][Django][Python] *http://code.google.com/intl/ja/appengine/articles/appengine_helper_for_django.html *http://code.google.com/p/google-app-engine-django/ !!概要 *Google App Engine は [WSGI|http://www.google.co.jp/custom?hl=ja&client=pub-4280062068315072&cof=FORID%3A1%3BGL%3A1%3BLBGC%3A336699%3BLC%3A%230000ff%3BVLC%3A%23663399%3BGFNT%3A%230000ff%3BGIMP%3A%230000ff%3BDIV%3A%23336699%3B&domains=typea.info%3Btypea.dip.jp&q=WSGI&btnG=%E6%A4%9C%E7%B4%A2&sitesearch=] 準拠のアプリケーションの実行をサポート *Django はこの規格をサポートしている *Google App Engine 上で実行する Django アプリケーションを構築(または既存のアプリケーションを移植)できる。 !WSGI(Web Server Gateway Interface) *http://ja.wikipedia.org/wiki/Web_Server_Gateway_Interface ::概要 *Python には多様な Webアプリケーションフレームワークが存在 *Web フレームワークの選択が使用できるWebサーバを制限したり、その逆の制限があったりする *WSGI はWebサーバとWebアプリケーションないしフレームワークとの間の簡潔で統一されたインタフェースを提示する ::仕様の概要 *WSGI のインターフェイスには二つの側面。 **"サーバ"ないし"ゲートウェイ"側 **"アプリケーション"ないし"フレームワーク"側 *アプリケーション側によって提供される呼び出し可能なオブジェクト(通常は関数やメソッド)を呼び出す。 *ミドルウェア の考え方を提供する。 *WSGI サーバーと WSGI アプリケーションの "中間に"挿入できるよう、WSGIミドルウェアは両方の側の API を実装。 *ミドルウェアはサーバーの観点からはアプリケーションとして動作し、アプリケーションの観点からはサーバーとして動作する。 !!Google App Engine 環境と Django 環境 !2つの大きな違い +Google App Engine は SQL データベースを提供しないので、Django の標準のモデルクラスは使用できない +Django が試みる特定のモジュールのインポートとアクション(テスト データベースの作成と削除など)が、Google App Engine では制限されている ""Google では、こうした違いのほとんどを配慮する必要がなくなるよう、ヘルパーを作成し、Google App Engine では機能しない Django の動作に対して、別の実装を提供 !!!以下実際の手順 基本的に、http://code.google.com/intl/ja/appengine/articles/appengine_helper_for_django.html を参考にするも、いろいろはまりポイントあり。 !![Python for Windows Extensions|http://sourceforge.net/projects/pywin32/]のインストール *Windows 上で、Google が提供する SDK インストーラを使用している場合は、[Python for Windows Extensions|http://sourceforge.net/projects/pywin32/](Win32 向け拡張モジュール。 Python から COM を操作できるようになる) をイントールして、SDK を自動検出できるようにする必要がある {{ref_image gae_django02.jpg}} !!ヘルパー !ダウンロード *http://code.google.com/p/google-app-engine-django から、appengine_helper_for_django-r86.zip をダウンロードした。 *ただ、CurrentDownloadにエントリがなく、上記ファイルはDeprecatedとなってしまっている。。。 !解凍と配置 *[上記サイト|http://code.google.com/intl/ja/appengine/articles]では、"mysite という名前のディレクトリに展開" との記述があるが、これは[Djangoのチュートリアル|http://docs.djangoproject.com/en/dev/intro/tutorial01/?from=olddocs]に習ったもので深い意味はない。 *Eclipse PyDevを利用しているので、プロジェクトのディレクトリに配置し、起動する。 {{ref_image gae_django03.jpg}} どうやら動いたようだ。WARNINGは現時点では気にしなくて良いとのこと。 ""WARNING で始まる行は無視して構いません。これは、データストアのデータを読めない、または PIL に問題があることを示しています。開発データストアにまだデータがなく、Python イメージングライブラリがコンピュータにインストールされていないことを警告しているだけです。 !!起動してみる !ImportError: No module named _multiprocessing *エラー第1弾。以下を参考に対処してみる。 *http://d.hatena.ne.jp/tmatsuu/20090818/1250606215 {{ref_image gae_django04.jpg}} !Django 1.0 or greater is required! *エラー第2弾。どうもヘルパーはDjango 1.0 以降を要求しているようだ。 {{ref_image gae_django05.jpg}} +http://code.google.com/p/googleappengine/downloads/list から、GoogleAppEngine_1.2.5.msi をダウンロードしてインストールしてみる・・・が、同梱されるDjangoは、0.96のようだ・・・ +[Djangoのサイト|http://www.djangoproject.com/download/]から、Django-1.1.tar.gz.をダウンロードして、プロジェクトの直下に配置する。 !TypeError: Initialization arguments are not supported *エラー第3弾。なかなか一筋縄ではいかない。。。 {{ref_image gae_django06.jpg}} *http://code.djangoproject.com/ticket/10727 を見ると、どうもDjangoのバージョンが新しくてもだめなようだ。もう一度、一つ前のリリース Django-1.0.3.tar.gz をダウンロードして、配置する。 {{ref_image gae_django07.jpg}} *構成は以下のような感じ。 **appengine_django ・・・ appengine_helper_for_django-r86.zip **django ・・・ Django-1.0.3.tar.gz を展開したファイルからdjangoディレクトリ配下 {{ref_image gae_django08.jpg}} !!It worked #1 *とりあえずローカル環境で動いている(?)ようだ。道のりは長い。 {{ref_image gae_django09.jpg}} !!zipimport *プロジェクト配下にDjangoを置いたが、GAEでは、ファイル数に上限(1000)があり、このままでは発行できない。 *djangoディレクトリをアーカイブして、そこからロードするzipimportという機能が利用できる。 *http://code.google.com/intl/ja/appengine/articles/django10_zipimport.html !zipで圧縮して・・・ {{ref_image gae_django11.jpg}} !main.pyに以下を追加 # Add Django 1.0 archive to the path. django_path = 'django.zip' sys.path.insert(0, django_path) !!It worked #2 {{ref_image gae_django12.jpg}} !!サーバーに発行 C:\Program Files\Google\google_appengine>appcfg.py update "C:\Program Files\eclipse3.4R2\workspace\typea-services\src" C:\Program Files\Google\google_appengine\appcfg.py:41: DeprecationWarning: the sha module is deprecated; use the hashlib module instead os.path.join(DIR_PATH, 'lib', 'antlr3'), Scanning files on local disk. Initiating update. Error 403: --- begin server output --- You do not have permission to modify this app (app_id=u'google-app-engine-django'). --- end server output --- *上記エラー。ヘルパーのアプリケーションIDのままになっていたので、自分のIDに修正 {{ref_image gae_django13.jpg}} !!It worked #3 よーーーやっとうごいた。 {{ref_image gae_django14.jpg}} !!!アプリケーションの作成 !!ソースフォルダで、python manage.py startapp を実行 ::実行コマンド python manage.py startapp [app_name] ::実行例 C:\Program Files\eclipse3.4R2\workspace\typea-services\src>python manage.py startapp gaetest C:\Program Files\Google\google_appengine\google\appengine\api\datastore_file_stub.py:40: DeprecationWarning: the md5 module is deprecated; use hashlib instead import md5 C:\Program Files\Google\google_appengine\google\appengine\api\memcache\__init__.py:31: DeprecationWarning: the sha module is deprecated; use the hashlib module instead import sha WARNING:root:Could not read datastore data from c:\docume~1\admini~1\locals~1\temp\django_typea-services.datastore WARNING:root:Could not read datastore data from c:\docume~1\admini~1\locals~1\temp\django_typea-services.datastore.history WARNING:root:Could not initialize images API; you are likely missing the Python"PIL" module. ImportError: No module named _imaging INFO:root:zipimporter('C:\\Program Files\\eclipse3.4R2\\workspace\\typea-services\\src\\django.zip', 'django\\core\\serializers\\') *geatest 以下が作成される {{ref_image gae_django15.jpg}} !!モデルの作成 *[Djangoチュートリアルでのモデル作成|/tips/wiki.cgi?page=Django+%BA%C7%BD%E9%A4%CE%A5%A2%A5%D7%A5%EA%A5%B1%A1%BC%A5%B7%A5%E7%A5%F3+1#p12] !ファイルの配置 {{ref_image gae_django17.jpg}} !models.pyの編集 *モデルを作成するには、ヘルパーが提供するモデル クラスと、Google App Engine のデータストアプロパティを使用する必要がある。 *Django標準のモデル クラスとプロパティ クラスは機能しない。 *モデルでは Djangoモデルクラスは使用されないが、ヘルパーによって Djangoモデルと同様に取り扱うことができ、モデルは Djangoに登録される。 from appengine_django.models import BaseModel from google.appengine.ext import db # Create your models here. class GaeTest(BaseModel): message = db.StringListProperty() create_date = db.DateTimeProperty('data created') !!APIをShellから使用する !python manage.py shell コマンドを実行 ::実行例 (モデルを保存してみる) C:\Program Files\eclipse3.4R2\workspace\typea-services\src>python manage.py shell : Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>> from gaetest.models import GaeTest >>> import datetime >>> g = GaeTest(message='first gae model.',create_date=datetime.datetime.now()) >>> g.save() datastore_types.Key.from_path(u'GaeTest', 1, _app_id_namespace=u'typea-services' ) !!モデルの有効化 *[Djangoチュートリアルでのモデルの開始|/tips/wiki.cgi?page=Django+%BA%C7%BD%E9%A4%CE%A5%A2%A5%D7%A5%EA%A5%B1%A1%BC%A5%B7%A5%E7%A5%F3+1#p15] *Google App Engine を使用するときは、モデルのデータベース テーブルを明示的に作成する必要はない。 *そのため sql*、syncdb、validate のコマンドは不要。ヘルパーはこれらのコマンドを使用しないように、manage.py から削除する。 *モデルを有効化するために必要なことは、settings.py を編集し、[INSTALLED_APPS に追加する|/tips/wiki.cgi?page=Django+%BA%C7%BD%E9%A4%CE%A5%A2%A5%D7%A5%EA%A5%B1%A1%BC%A5%B7%A5%E7%A5%F3+1#p11]だけ。 *settings.py INSTALLED_APPS = ( 'appengine_django', # 'django.contrib.auth', # 'django.contrib.contenttypes', # 'django.contrib.sessions', # 'django.contrib.sites', 'gaetest', # この行を追加 ) !!管理サイト *Django 管理サイトは SQL データベースのコンセプトと密接に関係しているため、Google App Engine ではサポートされていない。 *開発用 appserver により、代わりの管理インターフェースが、/_ah/adminで自動的に提供される。 *http://localhost:8080/_ah/admin/datastore {{ref_image gae_django16.jpg}} !!!ビュー、テンプレートの作成〜実行 *[Djangoチュートリアル|/tips/wiki.cgi?page=Django+%BA%C7%BD%E9%A4%CE%A5%A2%A5%D7%A5%EA%A5%B1%A1%BC%A5%B7%A5%E7%A5%F3+3#p7] *動作確認のため、簡単に実装 !!urls.pyの編集 ::settings.pyファイルのROOT_URLCONF 設定 にて、URLマッピングファイルを指定 ROOT_URLCONF = 'urls' ::urls.pyに以下の行を追加 *タプルに、正規表現、ハンドラを記述する *正規表現にマッチするリクエストがハンドラによって処理される urlpatterns = patterns('', (r'^gaetest/$', 'gaetest.views.index'), # 初期表示 (r'^gaetest/add/$', 'gaetest.views.add'), # データ追加 ) !!views.pyの編集 *ハンドラの実装 *上記、urls.py の正規表現に一致するリクエストがここで処理される *[GAEのデータストアAPI|http://code.google.com/intl/ja/appengine/docs/python/gettingstarted/usingdatastore.html]を利用してデータを登録、検索 from django.shortcuts import render_to_response from gaetest.models import GaeTest import datetime def index(request): g_list = GaeTest.gql('order by message') return render_to_response('gaetest/index.html', {'g_list':g_list}) def add(request): msg = request.POST['message'] g = GaeTest(message=msg, create_date=datetime.datetime.now()) g.save() g_list = GaeTest.gql('order by message') return render_to_response('gaetest/index.html', {'g_list':g_list}) !!index.html の編集 *テンプレートの作成 *上記views.pyで処理され、結果がコンテキストに与えられているので、それに基づいて画面を生成
message:
{% if g_list %} {% else %}

No GaeTest are available.

{% endif %} !!動いた {{ref_image gae_django18.jpg}}