Edited at

Python Django入門 (6)

More than 1 year has passed since last update.


スマホ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.urls import path

from api import views

app_name = 'api'
urlpatterns = [
# 書籍
path('v1/books/', views.book_list, name='book_list'), # 一覧
]

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

from django.contrib import admin

from django.urls import path, include

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


結果の確認

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

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

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

{

"books": [
{
"id": 1,
"name": "Django 入門",
"publisher": "GeekLab.Nagano",
"page": 100,
"impressions": [
{
"id": 1,
"comment": "あああ\r\nいいい"
},
{
"id": 2,
"comment": "ううう\r\nえええ"
},
{
"id": 4,
"comment": "コメント\r\nです。"
}
]
},
{
"id": 2,
"name": "書籍2",
"publisher": "GeekLab.Nagano",
"page": 200,
"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 をやってみることによって、さらに理解が深まると思います。