django-tastypieを使ってDjangoアプリにAPIを追加する

django-tastypieを使えば、Djangoでモデル定義されたデータへアクセスするAPIを簡単に作成することができます。できるみたい。
どのくらい簡単か試してみました。

インストール

pip install django-tastypie

0.9.11が入りました。

サンプル

とりあえずモデル

models.py

from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=255)
    pub_date = models.DateTimeField(auto_now_add=True)


モデルに対してModelResourceクラスが必要です


resources.py

from tastypie.resources import ModelResource
from tastypie.authorization import Authorization
from app.models import Book

class BookResource(ModelResource):
    class Meta:
        queryset = Book.objects.all()
        authorization = Authorization()


あとはModelResourceにアクセスするURLを定義

urls.py

from django.conf.urls import patterns, include, url
from app.resource import BookResource

book_resource = BookResource()

urlpatterns = patterns('',
    url(r'^api/', include(book_resource.urls)),
)


どシンプルな最低限の使い方。これでsyncdbすればとりあえずは動かせる。


requestsでアクセスしてみる


登録、更新、削除1件、削除全件と動かしてみたサンプル。requestsは便利

# coding=utf-8

import requests
import json


# データを全部削除
r = requests.delete('http://localhost:8000/api/book/')
assert(r.status_code == 204)

# データが全て消えていることを確認
r = requests.get('http://localhost:8000/api/book/')
# r.text {"meta": {"limit": 20, "next": null, "offset": 0, "previous": null, "total_count": 0}, "objects": []}
assert(json.loads(r.text)["meta"]["total_count"] == 0)

# 登録
payload = {'title': u'Python Cook Book', 'pub_date': "2012/9/25"}
r = requests.post('http://localhost:8000/api/book/', data=json.dumps(payload), headers={"Content-Type": "application/json"})
assert(r.status_code == 201)

# 取得
r = requests.get('http://localhost:8000/api/book/')
# r.text {"meta": {"limit": 20, "next": null, "offset": 0, "previous": null, "total_count": 1}, "objects": [{"id": "1", "pub_date": "2012-09-19T11:46:47.384764+00:00", "resource_uri": "/api/book/1/", "title": "Python Cook Book"}]}
res = json.loads(r.text)
assert(len(res["objects"]) == 1)
assert(res["objects"][0]["title"] == u"Python Cook Book")
assert(res["objects"][0]["id"] == "1")

# idを指定して取得
r = requests.get('http://localhost:8000/api/book/1')
# r.text {"id": "1", "pub_date": "2012-09-19T11:47:18.049405+00:00", "resource_uri": "/api/book/1/", "title": "Python Cook Book"}
res = json.loads(r.text)
assert(res["id"] == "1")
assert(res["title"] == u"Python Cook Book")

# 更新
payload = {'id': 1, 'title': u'Python Cook Book 2nd Edition', 'pub_date': "2013/1/25"}
r = requests.post('http://localhost:8000/api/book/', data=json.dumps(payload), headers={"Content-Type": "application/json"})
assert(r.status_code == 201)


# 更新内容を確認
r = requests.get('http://localhost:8000/api/book/1')
# r.text {"id": "1", "pub_date": "2013-01-25T06:00:00+00:00", "resource_uri": "/api/book/1/", "title": "Python Cook Book 2nd Edition"}
res = json.loads(r.text)
assert(res["id"] == "1")
assert(res["title"] == u"Python Cook Book 2nd Edition")


# idを指定して削除
r = requests.delete('http://localhost:8000/api/book/1')
assert(r.status_code == 204)

# データが消えていることを確認
r = requests.get('http://localhost:8000/api/book/1')
assert(r.status_code == 404)


requestsを使う場合、登録時、更新時にContent-Typeを指定しないとこんなエラーになります

{"error_message": "The format indicated 'application/x-www-form-urlencoded' had no available deserialization method. Please check your ``formats`` and ``content_types`` on your Serializer.", "traceback": "...."}