疑問の源泉
Djangoのチュートリアル part4 (ver2.2)で初出の django.urls.reverse
メソッド。(以下最終行)
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from .models import Choice, Question
# ...
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
最終行の reverse('polls:results', args=(question.id,))
は、以下view.py
の4行目と紐づいてリダイレクトURLが生成されクライアントへ返されるんだろうな、ということは分かるんですが、、、
urlpatterns = [
path('', views.index, name='index'),
path('\<int:question_id>/', views.detail, name="detail"),
★path('\<int:question_id>/results/', views.results, name="results"),
path('\<int:question_id>/vote/', views.vote, name="vote")
]
なんで reverse? 何を"逆"にしているんだろう?何かひっくり返してる?
"逆"ではない"順"は何なのだろう?
という疑問が浮かびこのコードが頭にスッと入ってこない。というのが発端です。
というのも、直前まで触っていたFlaskだと redirect(url_for('polls.results'))
のように書けて、resultsへのURLを生成、という風に読んで字のまま直感で分かりやすかったのでなおさら「Djangoはなんでここでreverseなんだ」と。
調べた方法:公式ドキュメント内で"reverse"と検索
パッと見それっぽいリンクが2つ見つかったので、この2つをざっと読みました。
が、django.urls utility functions の方はメソッドの定義で「あぁ、それでreverse/逆なのか」とピンとこず。
URL Dispatcher を読んでみると、イメージできるようになりました。
URL->viewの解決が"順"、view->URLの解決が"逆"
Django provides a solution such that the URL mapper is the only repository of the URL design. You feed it with your URLconf and then it can be used in both directions:
- Starting with a URL requested by the user/browser, it calls the right Django view providing any arguments it might need with their values as extracted from the URL.
- Starting with the identification of the corresponding Django view plus the values of arguments that would be passed to it, obtain the associated URL.
The first one is the usage we’ve been discussing in the previous sections. The second one is what is known as reverse resolution of URLs, reverse URL matching, reverse URL lookup, or simply URL reversing.
上記引用の太字部分から、
- ユーザからサーバへのリクエスト = URLをもとに対応するviewを見つける =
URL -> view
= これが"順" - viewをもとに対応するURLを見つける =
view -> URL
= これが"逆"
ということが分かりました。
正直、URL ⇔ ビュー間の正引き/逆引きという概念を全く意識しておらずごっちゃにしていました。
Pythonの Explicit is better な精神を垣間見た気がします。