スマホ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),
]
INSTALLED_APPS への追加
api アプリケーションをインストールしたことを、プロジェクトに教えてあげる必要があります。
model も template もないので、なくても動きますが、一応やっておきましょう。
api/apps.py
を開いてみると、ApiConfig というクラスが定義されています。
これを mybook/settings.py
の INSTALLED_APPS
の最後に 'api.apps.ApiConfig',
という文字列で追加します。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'cms.apps.CmsConfig', # cms アプリケーション
'api.apps.ApiConfig', # api アプリケーション
'bootstrap4', # django-bootstrap4
]
結果の確認
それでは、ブラウザで以下の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 をやってみることによって、さらに理解が深まると思います。