django-pistonでRestfulなWebAPIを簡単につくる

投稿日:2010/10/31 16:31:07

先日Twitterでつぶやいてたdjango-pistonですが、グーグル先生に聞いても日本語の記事はほとんど見つからなかったんで、わたくしが書いてみようと思います。

django-piston はもともとBitbucketのWebAPIのために作られた(多分)もので既存のDjangoのモデルを利用して簡単にRestfulなWebAPIが作れるという代物です。個人的には、いつか使ってみようと思いながら機会がなかったんですが、最近iPhoneアプリ作ってて、サーバ側の実装に使えそうだと思ったので使ってみました。

主な機能としては、

  • RestfulなWebAPIっぽく、GET POST PUT DELETE を受けれる
  • 1時間に50回までとかAPI呼出回数の制限をデコレータでつけられる
  • ベーシック認証とOAuth認証に対応
  • ドキュメント生成
  • Djangoのformを利用したバリデーション

今回は、だいぶ前に @soundkitchen 氏に作ってもらったこのブログを使って実験してみます。ちなみにこのブログのソースは bitbucket にて公開しはじめました。場当たりでDjangoのバージョンアップにだけ対応してきたのでちょっと古いコードとかもありそうだし、いろいろいじりたいと思ってます。

今回の動作サンプルはこちら

そしたらこのブログのエントリーを取得できるようなAPIを書いてみます。現在のエントリー部分のモデルは、↓のような感じです。とりあえずこの中からいくつかのフィールドを持ってくるようにしてみます。

class Entry(models.Model):
    """
    blog's entry.
    """
    title = models.CharField(_(u'title'), max_length=255, default=None)
    slug = models.SlugField(_(u'slug'))
    description = models.TextField(_(u'description'))
    comments_count = models.IntegerField(_(u'comments count'), editable=False, default=0)
    trackbacks_count = models.IntegerField(_(u'trackbacks count'), editable=False, default=0)
    created_at = models.DateTimeField(_(u'created at'), editable=False, default=datetime.now)
    updated_at = models.DateTimeField(_(u'updated at'), editable=False)
    published_at = models.DateTimeField(_(u'published at'), editable=False, blank=True, null=True)
    is_published = models.BooleanField(_(u'is published'), default=True)
    is_active = models.BooleanField(_(u'is active'), default=True)
    tags = models.ManyToManyField(Tag)

とりあえず、django-pistonのインストール。最新版は0.22なんですが、これだとDjango1.2以降でPOSTするときにCSRF用のトークンがないって言われて動かないのでtip版の0.23rc1を使ってます。

まずは、プロジェクトのルートにapiというディレクトリとurls.py、handlers.py をそれぞれ作成します。

$ mkdir api
$ touch api/__init__.py
$ touch api/urls.py
$ touch api/handlers.py

次に、プロジェクトルートのurls.pyに手を加えます。

(r'^api/', include('api.urls')),

これを追記して、/api/以下へのアクセスは、api/urls.pyに丸投げしましょう。そして、api/urls.pyの中身は↓のような感じ。

from django.conf.urls.defaults import *
from piston.resource import Resource

from api.handlers import EntryHandler

entry_resource = Resource(EntryHandler)

urlpatterns = patterns('',
    (r'^posts/$', entry_resource),
    (r'^post/(?P<entry_id>\d+)/$', entry_resource),
)

EntryHandlerはこれからapi/handlers.pyに書くやつです。ここでは、/api/posts/ に来たときと /api/post/1/ とかに来たリクエストをさばく設定をしました。そして、api/handlers.py は↓な感じ

#vim:fileencoding=utf8
from piston.handler import BaseHandler

from blog.models import *


class EntryHandler(BaseHandler):
    """
    ブログのエントリーを返す
    """
    allowed_methods = ('GET',) # GETだけ受けつける
    fields = ('title', 'description', 'created_at', 'updated_at', 'get_absolute_url', 'tags') # 取得したいフィールド
    exclude = () # 除外するフィールド(これを空にしておかないとデフォルトでは、idが省かれる)
    model = Entry # モデル

    def read(self, request, entry_id=None):
        """
        entry_idがある場合は単一のエントリー。
        なければ最新の10個。
        """
        if entry_id:
            try:
                instance = Entry.objects.get(pk=int(entry_id))
            except Entry.DoesNotExist:
                return rc.NOT_FOUND # 404 を返すショートカット
        else:
            return Entry.objects.all()[:10] # 10個もってくる
        return instance

とりあえずこんな感じで動きます。GETのリクエストを受けるのがreadメソッドとかPOSTを受けるのが、createメソッドとかっていう決まりがあるんですが、今回はとりあえずGETだけ受けつけるようになってます。ちなみに、デフォルトではJSONでレスポンスが返るんですが、/api/posts/?format=xml とかするとXMLで返してくれます。

今回は疲れたのでここまでで、次はPOSTとかPUTとかDELETEも受け付けてみようと思います。

Posted at: 
2010/10/31 16:31:07
0 Comments
1 TrackBack
Tags: 
Django
Trackback: 
http://blog.monospace.jp/2010/10/31/django_piston_intro/trackback/
この日記のはてなブックマーク数

TrackBacks

[Python][Django]django-pistonとbpmappersでWebAPIを作る - 偏った言語信者の垂れ流し

hfunaiの記事に便乗。 django-pistonでRestfulなWebAPIを簡単につくる - monospace blog django-pistonを使うとDjangoで簡単にWebAPIを作れます。 jespern / django-piston / wiki / Home ? Bitbucket fields/excludeにフィールド名を指定すると、必要なフィールドのみを出

Created at: 
2010/11/27 01:31:33

Comments

スパムコメントしか来ないのでコメント欄はリードオンリーです。コメントはTwitterなどでおねがいします。

まだ登録されていません。