知識の枝

"All is well"

Django リダイレクト時に変数を渡す

約101日前 2021年7月19日22:01
デジタル
Django JavaScript

改訂履歴


2021/7/19 投稿

1. 背景


Djangoを使った開発中に覚えたことを備忘録として残します。

今回はページをリダイレクトする際に好きな変数を次のビューに渡す方法を解説します。


2. ゴール


最初にアクセスしたときだけメッセージを表示するページを作る。


3. はじめに


今ちょうど食材を管理するアプリを作っていまして、「料理を作ったら、料理の実施履歴ページに移動する」部分を実装しています。

自動で履歴ページに移動した際に「調理しました!」というメッセージを表示させたいと思ったので、その機能を付けてみることにしました。

完成イメージはこんな感じです。



レシピ画面で人数と追加する食材を選んだ後、確定ボタンを押すと「履歴ページ」に移動する流れです。

あとからこの履歴ページにアクセスしても、「調理しました!」のメッセージは表示されません。

では実装方法をみていきましょう。



4. 実装方法


4.1 - Query String Parameters


この機能の実装に利用したのは「Query String Parameters」というものです。

始めて聞く単語だと思うので簡単に説明します。


ネットサーフィンをしていると、たまに「https://example.com/?●●=▲▲&■■=★★」のように「?」で始まる文字がくっついたURLを見かけることがあると思います。

この?で始まる部分が「Query String Parameters」です。



上記の例では「?cooked=done」の部分が該当します。

「cooked」という変数に「done」という文字列が入っているイメージです。

変数が複数ある場合は「&」で繋げて書くことができます。


そしてなんと、このパラメーターがあっても無くても同じページが開きます!

「https://example.com/?●●=▲▲&■■=★★」

「https://example.com/」と同じページが開き、ついでに変数「●●」と「■■」というパラメーターをもった状態になります。


このパラメータを上手く活用して目標を達成したいと思います。


4.2 - URLの使い分け


「パラメーターがあっても無くても同じページが開く」という特徴を使って「最初にアクセスしたときだけメッセージを表示する」という機能を実装します。

やり方はこうです。

「料理をつくる」ボタンを押して履歴ページに移動する際のURLにはパラメーターを付与。

それ以外の場合、例えば料理履歴一覧ページから開くときはパラメーターを無しにします。



「パラメーターの有無」を検出して「メッセージの表示有無」を切り替えれば、上記の機能を実装できます。



4.3 - パラメーターの付与


上記の手段を用いるのであれば、レシピページから履歴ページへの移動時のみURLにパラメーターを付与する必要があります。

方法は2通りあります。

1つは使い慣れたリダイレクト関数「redirect()」を使う方法。

もう一方は「Ajax」処理の中でリダイレクトを行う方法です。


ではまず、redirect() を使う方法から。

やりたいことは移動先(リダイレクト先)のURLに「?●●=▲▲」を付けたいだけです。

ですので、流れとしては単純で

①移動先のURLを取得する

②URLに「?●●=▲▲」を付ける

③そのURLに移動する


ということになります。

まず始めに移動先ページのURLを取得しましょう。
別に直接書いちゃってもOKです。
url = reverse('app:next_view', kwargs={'key':value})
print(url)
>> https://exampe.com/next/value/ #取得例

#直接書く場合
url = "https://example.com/next/" + str(value) + "/"
print(url)
>> https://exampe.com/next/value/

どちらの場合も value は変数として解釈して下さい。

続いてURLの最後に「?●●=▲▲」を付けます。
こちらも先ほどと同様に直接書いても良いですし、楽をしても良いです。

渡したい「変数」と「値」の組み合わせを下記だとします。
変数:cooked
値:done

付け足したい文字列は「?cooked=done」ですね。
#直接書く場合
new_url = url + "?cooked=done"


#pythonらしく書く場合
parameter = {'cooked': done} #辞書で定義します
query_string_parameter = urlencode(parameter) #URLエンコードしてURLで使える形に変えます
new_url = url + "?" + query_string_parameter #合体
urlencode()に引数として辞書を与えると、URLで使える形に直してくれます。

上記の例だと
query_string_parameter = urlencode(parameter)
print(query_string_parameter)
>> "cooked=done"
となります。

パラメーターの数が多い場合は2つ目の方法のほうがスマートだと思います。

最後に作ったURLへ移動します。
return redirect(new_url)


redirect()を使った方法は以上です。



続いて、「Ajax」処理の中でリダイレクトを行う方法を解説します。

Ajax処理でhtmlからviews.pyに戻ってきている場合、ビューの中でredirect()を使うことができません。
(エラーは出ませんが機能しないです)

仕方ないのでビューの中でリダイレクトはせず、htmlに再度戻ってからリダイレクトします。
views.py   #リダイレクト処理を行わない
~~~色々な処理~~~
d = {
'cooked_id': cooked.cooked_uuid,
}
return JsonResponse(d)
リダイレクト先のURLに<int:pk>のようなキーが必要な場合は、上記のように定義してhtmlに渡しておきます。

続いてhtml側の処理です。

Ajaxでレスポンスが返ってきたところからです。
.done(response => {
window.location.href='/cookme/{{storage_id}}/history/' + response.cooked_id + '/' + '?cooked=done'
});
「window.location.href=」でリダイレクト先のURLを指定します。

Djangoのテンプレート変数も普通に使えます。
「'/cookme/{{storage_id}}/history/'」

先ほどビューから受け取った変数も使えます。
「response.cooked_id」

最後にQuery String Parameterを手入力しています。
ここだけアナログです。
「'?cooked=done'」

上記の文字列はビューの中で作っておいて、変数としてJSONResponseで一緒に渡しても良いです。

その場合は下記のように書くと良いでしょう。
#下記query string parameterの定義方法は自由です
query_string_parameter = "/?cooked=done" #とりあえず手入力

d = {
'cooked_id': cooked.cooked_uuid,
'cooked': query_string_parameter, #変数として渡す
}
return JsonResponse(d)


html側
.done(response => {
window.location.href='/cookme/{{storage_id}}/history/' + response.cooked_id + response.cooked
});
こんな書き方でできると思います。


Ajaxの場合の方法は以上です。



4.4 - パラメーターの取得


リダイレクト先のビューで先ほど定義したパラメーターを取得します。

URLにQuery String Parametersがある状態のときに、下記コードを実行すると変数を取得できます。
views.py
def HistoryDetailView(request, storage_id, cooked_id):
"""調理履歴詳細ページ"""
"""調理後か否か"""
after_cooked = request.GET.get('cooked')

#メッセージを作成
if after_cooked:
success_message = '<div class="alert alert-info" role="alert">調理しました!</div>'
else:
success_message = ""

#メッセージをhtmlに渡す
context = {
'success_message': success_message,
}

return render(request, template, context)
URLをパラメーターを取得するコードは「request.GET.get('URLの変数名')」です。

あとは「変数を取得したか否か」でメッセージを作る分岐を行います。

上記の例では、変数があった場合には「調理しました!」というメッセージを作っています。

最後に作ったメッセージをhtmlに渡します。


4.5 - メッセージの表示


ビューから受け取ったメッセージを表示します。

htmlに先ほどのテンプレート変数「success_message」を書きます。
{{success_message|safe}}
htmlとして表示させたいので「safeフィルター」を用いています。


以上で、「最初にアクセスしたときだけメッセージを表示する」という機能を実装することができました!



5. さいごに


今回のようにメッセージを表示したいときのベストな方法かは分かりませんが、知っている機能を組み合わせれば色々なことができます。

少しずつ知識を増やして、やりたいことが出来るようになるといいですね!