データベースからの推薦リストの取得
データベースから推薦リストを取得するようにしてみましょう。データベースにアクセスするためにはサーバと通信する必要があります。クライアントからリクエストデータをサーバに送信し、サーバで処理された結果をレスポンスデータとしてクライアントに返す、という処理を行うことになります。サーバと通信するための方法の一つとして、Ajaxを用いる方法があります。ここでは、Ajaxによるクライアントとサーバとの通信方法について説明します。なお、Ajaxの詳細については文献[1]を参照してください。
ここでは、ランダム推薦システムによる推薦リストを取得できるようにしてみましょう。まずは、サーバとの通信処理としてMainPage.js
のMainPage
クラスに下記のgetRandomRecommendations()
メソッドを追加してください。
リスト1: recsys_django/static/js/MainPage.js
/**
* ランダム推薦システムによる推薦リストを取得する。
*/
getRandomRecommendations() {
let thisPage = this;
$.ajax({
url: 'random/',
method: 'GET',
data: {
},
timeout: 10000,
dataType: 'json',
}).done(function(response) {
let description = response.description;
let reclist = response.reclist;
console.log(description, reclist);
}).fail(function(response) {
window.alert('MainPage::getRandomRecommendations() : failed');
});
}
getRandomRecommendations()
メソッドは、サーバと通信し、サーバから推薦リストを取得した後、その推薦リストをコンソールに表示します。例えば、ブラウザがGoogle Chromeの場合、ブラウザの右上のメニューからその他のツール > デベロッパー ツールを選択するか、F12キーを押すことでデベロッパーツールが表示されます。そのデベロッパーツールからConsoleタブを開くことで、コンソールが表示されます。コンソールには、エラーメッセージなどデバッグに重要な情報が出力されます。JavaScript上では、console.log()
メソッドを用いることで、コンソールにメッセージを出力させることができます。
getRandomRecommendations()
メソッドにはAjaxによる通信に関するコードを記述しています。Ajaxによりクライアントとサーバが通信するためには、jQueryで提供されている$.ajax()
メソッドを呼び出します。$.ajax({...})
の部分はサーバに伝える情報です。.done(function(response) {...}
の部分には、サーバからレスポンスデータを受け取った後に実行する処理を記述します。
サーバに伝える情報は次のとおりです。
url
: リクエストデータ送信先のURLを指定します。ここでは、'random/'
を指定しています。method
:'GET'
や'POST'
などのリクエストメソッドを指定します。主に、サーバからデータを取得する場合には'GET'
を、サーバ上のデータを書き換える場合には'POST'
を指定します。ここでは、サーバから推薦リストを取得するため'GET'
を指定しています。data
: サーバに送信するリクエストデータを{キー: 値}対の集合で指定します。今回は送信するデータはありませんので、この内容は空にしています。timeout
: サーバから一定時間応答がなかった場合、接続が中止されます。それをタイムアウトといいます。そのタイムアウトまでの時間をミリ秒単位で指定します。ここでは10秒としています。dataType
: サーバから受け取るレスポンスデータのデータ形式を指定します。ここではJSON形式を指定しています。
以上の情報を指定することで、サーバにリクエストデータを送信することができます。
リクエストデータをサーバに送信した後は、サーバ側でリクエストデータに基づく処理が実行され、その結果がレスポンスデータとしてクライアントに返ってきます。
サーバ側での処理が成功した場合は、.done(function(response) {...}
の部分の処理が実行されます。一方で、サーバ側で何らかのエラーが発生するなど、処理が失敗した場合は、.fail(function(response) {...}
の部分の処理が実行されます。
サーバからのレスポンスデータは、response
に格納されます。この例では、dataType
に'json'
を指定していますので、response
にはJSON形式のレスポンスデータが格納されています。今回の例では、レスポンスデータに含まれているresponse.description
とresponse.reclist
をそれぞれ変数description
とreclist
に格納しています。
つづいて、サーバ側の処理を記述します。online/views.py
に下記のRandomView
クラスを追加してください。
リスト2: recsys_django/online/views.py
import json # 追加
from django.views.generic import View
from django.shortcuts import render
from django.http import HttpResponse
from .models import Item # 追加
from .mappers import RecRandomMapper # 追加
...(略)...
# 以下を追加
class RandomView(View):
"""ランダム推薦ビュー
"""
def get(self, request, *args, **kwargs):
"""ランダム推薦リストを取得する。
Parameters
----------
request : WSGIRequest
リクエスト
Returns
-------
HttpResponse
推薦説明と推薦リストをJSON形式で返す。
"""
# オブジェクトの取得
reclist = list(Item.objects.order_by('?'))
recs = [RecRandomMapper(rec).as_dict() for rec in reclist]
# レスポンスの生成
description = '本日のおすすめ'
response = {
'description': description,
'reclist': recs,
}
response_json = json.dumps(response)
# レスポンスの返却
return HttpResponse(response_json, content_type='application/json')
このRandomView.get()
メソッドでは、データベースから推薦リストを取得し、それをレスポンスデータとして生成し、クライアントに返却します。
まず、# オブジェクトの取得
の部分で、Item.objects.order_by('?')
メソッドを用いてItem
モデルからすべてのデータをランダムに並び替えて取得しています。この結果を推薦リストreclist
として受け取っています。ただし、後でこの推薦リストをJSON形式として渡しやすくするため、辞書型に変換しておきます。推薦オブジェクトを辞書型に変換するためのマッパーを定義します。recsys_django/online/
ディレクトリにmappers.py
を作成し、下記のコードを記述してください。
リスト3: recsys_django/online/mappers.py
class RecRandomMapper:
"""ランダム推薦マッパー
Attributes
----------
rec : Item
推薦オブジェクト
"""
def __init__(self, rec):
self.rec = rec
def as_dict(self):
"""推薦オジェクトを辞書型として取得する。
Returns
-------
dict
推薦オブジェクトを辞書型にして返す。
"""
item = self.rec
return {
'rank': 1,
'item': {
'item_id': item.item_id,
'name': item.name,
'red': item.red,
'white': item.white,
'shining': item.shining,
},
'score': 1,
}
つづいて、RandomView.get()
メソッドの# レスポンスの生成
の部分では、レスポンスデータをJSON形式で生成しています。JSON形式は、{キー: 値}対の集合です。JSON形式の詳細は文献[2]などを参照してください。ここでは、推薦説明文を表す'description'
と推薦リストを表す'reclist'
を、それぞれキーとして定義しています。ここで、response
は厳密には辞書型になりますので、これをJSON形式にエンコードする必要があります。このエンコードにはjson.dumps()
メソッドを用います。これを利用するには、json
パッケージをインポートする必要があります。これが冒頭のimport json
です。JSON形式にエンコードしたレスポンスデータをresponse_json
としています。
最後に、# レスポンスの返却
の部分で、生成したレスポンスデータをクライアントに返却します。
これでサーバ側の処理が記述できました。後は、この処理がクライアント側から呼ばれるようにしましょう。まず、URLconf
を設定します。recsys_django/online/urls.py
に下記コードを追加してください。
リスト4: recsys_django/online/urls.py
from django.urls import path
from . import views
app_name = 'online'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('random/', views.RandomView.as_view(), name='random'), # 追加
]
このように、URLrandom/
にアクセスされたとき、views.RandomView.as_view()
が呼ばれるように設定しました。
さて、このURLrandom/
にはいつアクセスされるのでしょうか。それが、リスト1のgetRandomRecommendations()
メソッドの$.ajax({...})
で指定したurl
です。リスト1ではurl
にrandom/
を指定していました。したがって、ここからURLrandome/
にアクセスされるということになります。さらに、リスト1ではmethod
に'GET'
を指定していました。これにより、URLrandom/
にアクセスされたとき、リスト2のRandomView.get()
メソッドが呼ばれることになります。
最後に、main.js
のinitData()
関数から、リスト1のgetRandomRecommendations()
メソッドを呼び出すようにしましょう。main.js
のinitData()
関数に下記コードを追加してください。
リスト5: recsys_django/static/js/main.js
/**
* データの初期化
*/
function initData() {
currentPage = mainPage;
// 各推薦リストの取得
mainPage.getRandomRecommendations();
currentPage.draw();
}
ブラウザで下記のURLにアクセスしてみましょう。
http://localhost:8000/
画面上は変わりありませんが、コンソールを表示してみてください。
コンソールに「本日のおすすめ」と推薦リストの内容が出力されていれば、データベースからの推薦リストの取得に成功です。もし、正しく出力されず、「MainPage::getRandomRecommendations() : failed」というアラートが表示された場合は、サーバ上で何らかのエラーが発生しています。サーバから出力されたエラーメッセージを参照し、デバッグしてみましょう。
参考
- 現場で使える Django の教科書《実践編》 # 第4章 開発のヒント(Ajax対応とJSONレスポンス)
- JavaScript Object Notation - Wikipedia