WSGIとPythonでスマートなWebアプリケーション開発を

第5回WSGIで利用可能なWebアプリケーションフレームワーク

はじめに

前回は、 WSGIアプリケーションを動作させるためのプラットフォームとして、Google App Engine(GAE)を紹介しました。今回は、Webアプリケーションを作る上で役に立つ、WSGIが利用可能なWebアプリケーションフレームワークを紹介します。

Webアプリケーションフレームワークとは

アプリケーションフレームワークとは、簡単に言ってしまえば便利なライブラリの集まりです。ライブラリと違うのは、単に機能を提供するだけでなく、アプリケーションの組み立て方、ファイルの配置など、ライブラリとしての機能以上の概念を伴うことです。これは、アプリケーションの組み立て方を明確にすることでアプリケーションの作成を簡単にする、プログラマが道に迷わないようにする、という意味があります。

ひと口にWebアプリケーションフレームワークと言っても、Pythonに限定してもTurboGears、Pylonsなどさまざまなものがあります。今回はその中のさまざまなフレームワークの内、前回のまとめで挙げたDjangoを使用します。

Django

Djangoは、データベースを利用するWebアプリケーションを簡単に作るためのフレームワークです。DRYDon't Repeat Yourself:同じことを繰り返さない)の原則があり、コンポーネントの再利用性、機能追加の容易さ、素早い開発などの特徴があります。

Djangoは、O/Rマッパ、URLディスパッチャ、テンプレートシステムなどの機能からなります。それ以外に、Django上で動作するコンポーネントとして、データベースエントリの管理インターフェースや、コンテンツのキャッシュ機能などを持っています。

図1 ログイン画面
図1 ログイン画面
図2 Djangoのデータベース管理画面
図2 Djangoのデータベース管理画面

また、DjangoはGoogle App Engine でサポートされていて、SDKにもDjangoが同梱されています。GAEで利用する際には、ヘルパパッケージが存在するので、それを利用するとGAEでDjangoを容易に利用できます。

DjangoとGAEとの連携には、WSGIが使われています。これは、Django自体がWSGIアプリケーションとして動作可能なためです。

Djangoのインストール

Djangoのダウンロードページから、Django-1.0.tar.gzをダウンロードして展開します。

展開したディレクトリで

図3
$ python setup.py install

とセットアップスクリプトを実行するとインストールされます。インストールには管理者権限が必要です。

サンプルデータ

今回のサンプルデータは、django_sample.zip(ZIPで圧縮してあります)にあります。内容は前回と同様のMessageBoardアプリケーションをDjangoを使用して再実装したものです。ダウンロードして、適当なディレクトリに展開してください。

サンプルを展開したディレクトリに移動し、以下のコマンドを実行します。

図4
$ ./manage.py syncdb

これで、Djangoで使用するデータベースが初期化されます。実行中に、サイトの管理者名・メールアドレス・パスワードを聞かれるので、適当に設定してください。

そして、

図5
$ ./manage.py runserver

を実行すると、サーバが立ち上がります。

その後、http://localhost:8000/にアクセスすると、MessageBoardの画面が現れます。

空プロジェクトの作成と実行

それでは、DjangoでWebアプリケーションを作成してみます。

まず、適当なディレクトリで、

図6
$ django-admin ${プロジェクト名}

とすると、新しくプロジェクトが作成されます。ここでは、django_sampleというプロジェクト名を使用します。

プロジェクト名は、Pythonにインストールされているモジュール名と被らないようにする必要があります。たとえば、testと入力すると、標準モジュールと同名であるため、弾かれてしまいます。

作成したプロジェクトにあるファイルは、以下のとおりです。

ファイル名 意味
__init__.py ディレクトリをモジュールとして使うために必要
manage.py プロジェクトの管理を行うスクリプト
settings.py プロジェクトの設定スクリプト
urls.py URL割り当て設定を記述するスクリプト

実行すると、指定したプロジェクト名でディレクトリができているので、その中に移動し、

図7
$ ./manage.py runserver

とすると、サーバが立ち上がります。

そしてhttp://localhost:8000/にアクセスすると、次のような画面が現れ、アプリケーションの実行が成功したことが確認できます。

図8 Djangoサーバを起動したところ
図8 Djangoサーバを起動したところ

アプリケーションの作成

先ほど作成したのは、Djangoのプロジェクトです。今度は、プロジェクトの上にアプリケーションを作成します。

プロジェクトのディレクトリで

図9
$ ./manage.py startapp ${アプリケーション名}

と入力すると、アプリケーションが作成されます。ここでは、testappというアプリケーション名を使用します。

アプリケーションディレクトリには、以下のファイルが作成されます。

ファイル名 意味
__init__.py プロジェクトの時と同様
models.py データベースに保存するモデルを定義する
views.py 表示に使う関数などを定義する

プロジェクトの設定

作成したプロジェクトの設定を変更します。プロジェクトの設定は、settings.pyにあります。変更するのは以下の変数です。

変数名 値の説明
DATABASE_ENGINE 使用するデータベースのエンジンです。'sqlite3'を指定します。
DATABASE_NAME データベースを保存するファイル名です。 'dj.db'を指定します。
INSTALLED_APPS このプロジェクトで使用するアプリケーション一覧です。'django_sample.testapp'を追加します。

INSTALLED_APPSに追加するdjango.contrib.adminは、管理画面を表示するためのアプリケーションです。またdjango_sample.testappは、先ほど作成したアプリケーションです。名前を変更した方は、それに合わせて変更してください。

modelの定義

作成したtestappにある、models.pyを編集します。

リスト1 models.py
#-*- coding:utf-8 -*-
from django.db import models
import datetime

# Create your models here.

class Entry(models.Model):

    name = models.CharField(max_length=100)
    title = models.CharField(max_length=100)
    body = models.TextField()
    date = models.DateTimeField('post date')

    

def addEntry(name, title, body):

    item = Entry(name=name,
                 title=title,
                 body=body,
                 date=datetime.datetime.now())

    item.save()


    
def getEntries():

    return Entry.objects.order_by('-date')

中身は使用しているクラス以外は、前回GAEで定義したmodel.pyと変わらないため、説明は省略します。

viewの定義

views.pyを編集し、表示を行う機能を作成します。

リスト2 views.py
#-*- coding:utf-8 -*-
# Create your views here.

from django import shortcuts, http
import models

from xml.sax import saxutils


def listMessages(request):
    ''' エントリ一覧を出力 '''

    items = models.getEntries()

    esc = saxutils.escape

    for i in items:
        i.title = esc(i.title)
        i.name = esc(i.name)
        i.body = esc(i.body)

    response = shortcuts.render_to_response('index.html',
                                            {'title':'Message Board',
                                             'items':items,
                                             'posturl':'post/',
                                             'esc':saxutils.escape})
    
    return response



def addMessage(request):
    ''' エントリを追加 '''

    post = request.POST

    title = post.get('title', '')
    name = post.get('name', '')
    body = post.get('body', '')

    models.addEntry(name, title, body)

    return http.HttpResponseRedirect('..')

listMessagesとaddMessageを定義しています。addMessageは、リクエストデータの受け取り方やリダイレクトの方法以外は、基本的に前回のGAEからほとんど変わっていませんので、説明は割愛します。

listMessagesは、表示を行う際のHTML生成部分がページテンプレートに置き換えられ、render_to_response関数でレスポンスデータを作成しています。この関数では、第一引数で指定したテンプレートファイルを読み込み、実行してHTMLデータを生成します。第二引数の辞書は、テンプレート中で使用する変数を渡します。

ここで読み込むテンプレートは、INSTALLED_APPSに追加したアプリケーションのあるディレクトリのtemplatesディレクトリから読み込みます。テンプレートファイルの拡張子は.htmlです。ここでは、testappのディレクトリにtemplatesディレクトリを作成し、中にテンプレートファイルを追加します。

テンプレートファイルは、HTMLにデータの埋め込みや制御構文などの文法を追加したものです。

リスト3 テンプレートファイル(index.html)
<html>
  <head>
    <title>{{ title }}</title>
  </head>

  <body>
    {% for x in items %}
    <dl>
      <dt>Title</dt>
      <dd>{{ x.title }}</dd>
      <dt>Name</dt>
      <dd>{{ x.name }}</dd>
      <dt>Date</dt>
      <dd>{{ x.date }}</dd>
      <dt>Body</dt>
      <dd>{{ x.body }}</dd>
    </dl>
    <hr />
    {% endfor %}

    <form method="post" action="{{ posturl }}">
      <dl>
        <dt>Title</dt>
        <dd><input type="text" name="title" /></dd>
        <dt>Name</dt>
        <dd><input type="text" name="name" /></dd>
        <dt>Body</dt>
        <dd><textarea name="body"></textarea></dd>

        <input type="submit" value="post" />

    </form>

  </body>
</html>

{%%} で囲まれた部分には、forなどの制御構文を記述します。この例では、forを使用してitemsの中を走査しています。そして、 {{ }} で囲まれた部分は、変数による置換です。このようなテンプレート構文を利用することでHTMLに変数を埋め込むことができます。

テンプレートを使用すると、見栄えとロジックが分離され、管理しやすくなるというメリットがあります。

URLディスパッチの設定

最後に、クライアントからアクセスされた URL と、関数をマッピングする設定を行います。マッピングには、urls.pyを使用します。

リスト4 urls.py
from django.conf.urls.defaults import *

urlpatterns = patterns(
    '',
    # Example:
    # (r'^django_sample/', include('django_sample.foo.urls')),

    # Uncomment this for admin:
    # (r'^admin/', include('django.contrib.admin.urls')),
    ('^post/', 'django_sample.testapp.views.addMessage'),
    ('^', 'django_sample.testapp.views.listMessages'),
)

ここでは、patterns関数にマッピング情報を渡しています。第一引数は、マッピング先モジュールのプリフィクスです。マッピングする関数が同じもジュールにある場合、先頭の共通部分を定義しておくことができます。第二引数以降は、マッチに使用する正規表現と、マッチした結果呼び出される関数のモジュールパスを指定します。

まとめ

少々駆け足気味でしたが、以上がDjangoを使用したアプリケーションをの作成方法です。

このように、アプリケーションフレームワークでは、あらかじめ決められた作成法方に沿ってアプリケーションを作成していきます。このような方法は、作成する側からすると楽ですが、フレームワークの枠組みをこえた使い方をしづらい、アプリケーション全体の動作を把握しにくいといった欠点もあります。そのような利点と欠点を理解した上で、アプリケーションフレームワークを便利に利用すると良いと思います。

Django に関するドキュメントは、公式ページのものと日本のユーザ会のものとがあります。

今回でWSGIの特集は最後です。この特集が、 Web アプリケーション開発者の方々のお役に立てれば幸いです。最後まで読んでいただき、有難うございました。

おすすめ記事

記事・ニュース一覧