Python Django入門 (6)

  • 147
    いいね
  • 1
    コメント

スマホAPIを作る

ここまで、HTMLのレスポンスを返す、Webアプリケーションの例を見てきました。

次に、iOS/AndroidアプリのバックエンドとしてJSONを返す例を作ってみます。

Django REST frameworkのように、REST APIを作るモジュールを導入することもできますが、まずは自分で書いてみることにします。

apiアプリケーションの作成

mybook プロジェクトの下に api というアプリケーションを作成します。

$ python manage.py startapp api

mybook プロジェクトのディレクトリの下に、以下のファイルが作成されました。

mybook/
    api/
        __init__.py
        admin.py
        apps.py
        migrations/
            __init__.py
        models.py
        tests.py
        views.py

JSONを返すビュー

基本は、jsonモジュールを使って、Python辞書オブジェクトをJSONに変換します。

import json

data = {'id': 1, 'name': 'hoge'}
json_str = json.dumps(data, ensure_ascii=False, indent=2)
  • ensure_ascii=False # 日本語が含まれる時、このように指定。
  • indent=2 # 空白2個で整形する場合。省略すると整形しない。

ただし、Python辞書は順不同になるため、JSONの中身も順不同となってしまいます。

そこで、collections.OrderedDict 順序付き辞書を使います。

なお、OrderedDictが使えるのは、Python 2.7 からなので、サーバ環境によって Python 2.6 以下の場合は、orderddictを使います。

api/views.py は以下のようになります。

import json
from collections import OrderedDict
from django.http import HttpResponse
from cms.models import Book


def render_json_response(request, data, status=None):
    """response を JSON で返却"""
    json_str = json.dumps(data, ensure_ascii=False, indent=2)
    callback = request.GET.get('callback')
    if not callback:
        callback = request.POST.get('callback')  # POSTでJSONPの場合
    if callback:
        json_str = "%s(%s)" % (callback, json_str)
        response = HttpResponse(json_str, content_type='application/javascript; charset=UTF-8', status=status)
    else:
        response = HttpResponse(json_str, content_type='application/json; charset=UTF-8', status=status)
    return response


def book_list(request):
    """書籍と感想のJSONを返す"""
    books = []
    for book in Book.objects.all().order_by('id'):

        impressions = []
        for impression in book.impressions.order_by('id'):
            impression_dict = OrderedDict([
                ('id', impression.id),
                ('comment', impression.comment),
            ])
            impressions.append(impression_dict)

        book_dict = OrderedDict([
            ('id', book.id),
            ('name', book.name),
            ('publisher', book.publisher),
            ('page', book.page),
            ('impressions', impressions)
        ])
        books.append(book_dict)

    data = OrderedDict([ ('books', books) ])
    return render_json_response(request, data)

render_json_response() はJSONP にも対応しています。
スマホのAPIだけでなく、JavascriptのAjaxでJSONを取得する場合にも応用できます。

JSONを返すURL

api/urls.py というファイルを新規作成し、以下のように記述します。

from django.conf.urls import url
from api import views

urlpatterns = [
    # 書籍
    url(r'^v1/books/$', views.book_list, name='book_list'),     # 一覧
]

この api/urls.py を、プロジェクトの mybook/urls.py で include します。

from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^cms/', include('cms.urls', namespace='cms')),
    url(r'^api/', include('api.urls', namespace='api')),  # ここを追加
]

結果の確認

それでは、ブラウザで以下のURLを開いて下さい。

http://127.0.0.1:8000/api/v1/books/

結果は以下のようになります。

{
  "books": [
    {
      "id": 1, 
      "name": "Django入門", 
      "publisher": "GeekLab Nagano", 
      "page": 10, 
      "impressions": [
        {
          "id": 1, 
          "comment": "途中で\r\n眠くなった。"
        }, 
        {
          "id": 2, 
          "comment": "ああ"
        }, 
        {
          "id": 3, 
          "comment": "いい"
        }
      ]
    }, 
    {
      "id": 2, 
      "name": "Raspberry Pi 入門", 
      "publisher": "GeekLab Nagano", 
      "page": 15, 
      "impressions": []
    }
  ]
}

iOS/Androidアプリからのデータの受信

iOS/Androidアプリに対してデータを送信する場合は JSON でよいですが、データを受信したい場合はどうするのでしょうか。

  • 簡単なデータの場合は、Webアプリのフォーム受信と同じものを書いて、スマホ側では http form post を模倣してもらいます。
    • こうすることによって、データのエラーチェックは、フォームのバリデーションの仕組みが使えます。
    • 正常かエラーかは、JSONで結果を返すようにします。
  • 繰り返しがある複雑なデータは、スマホ側からJSONをPOSTしてもらい、json.loads() でデコードします。

JSONで受信する場合、request の raw_post_data からJSON文字列を取り出せます。

import json

def xxxx_post(request):
    python_obj = json.loads(request.raw_post_data)  # RequestのBodyが直接JSON文字列となるようPOSTしてもらう
      :

スマホAPIのまとめ

スマホAPIだけを作るのであれば、データ投入は Django の管理サイトの機能を使い、API部分だけを書く、といったことも可能です。

簡単にスマホのバックエンドを作成することができます。

なお、本格的にAPIを作成する場合は、Django REST frameworkの導入も検討してください。

最後に

ここまでで、この講座は終了です。

この講座の後に、公式チュートリアル その1〜7 をやってみることによって、さらに理解が深まると思います。