言いたいこと
Django ViewではHttpメソッドの関数が定義できます😊
定義した関数にHttpメソッドで振り分けられます。
私はGET
でしかできないものだと思っていました。
def get():
# 処理
def post():
# 処理
該当メソッドの呼び出し場所
該当メソッドの呼び出し場所は以下にあります。
from django.views.generic import View
以下、メソッドの呼び出し場所の抜粋です。
class View:
"""
Intentionally simple parent class for all views. Only implements
dispatch-by-method and simple sanity checking.
"""
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
# ここにdef __init__や def asViewメソッド類がありますが、
# 今回は関係ないので省略します
def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
def dispatch
が今回の解説の要です。
解説
1行目 - ifで分岐するが、基本は常にTrue
def dispatch
にある、メソッド内の1行目を参照します。
class View:
def dispatch(self, request, *args, **kwargs):
if request.method.lower() in self.http_method_names: # ←こいつの解説
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
まず、request.method
ですね。
リクエストのメソッドを示しています。
Djangoの公式ページには以下のような記述があります。
HttpRequest.method
リクエストに使われた HTTP メソッドを表す文字列です。必ず大文字になります。
if request.method == 'GET':
do_something()
elif request.method == 'POST':
do_something_else()
すなわち、request.method
にはHTTPメソッド名が入ることになります😊
メソッド名は大文字で渡されています。
例えば、以下のようなものですね。
'GET'
'POST'
'PUT'
続きを読んでいきます。
if request.method.lower() in self.http_method_names:
これらを.lower()
で小文字にしています。
ここまでで、request.method.lower()
が読み解けます。
**Httpメソッド名が小文字で入っている。**ということですね。
Httpメソッド名が小文字で入っている。
これを踏まえて続きを見ましょう。
self.http_method_names
があります。
これは以下のような変数が定義されています。
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
Httpメソッド名が羅列されています。
get
もpost
もありますね。
if request.method.lower() in self.http_method_names:
よって、1行目if文の結論としては
Httpメソッド名の場合にTrueとなる。
という結果になります。
要は、いつでもif文をTrueを通過するという認識です。
http_method_namesから'get'
や'post'
の記述を消せば、Falseになりますね。
ここらへんはカスタマイズ可能な作りになっているようです。
2行目- 定義された関数を呼び出す
class View:
def dispatch(self, request, *args, **kwargs):
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(), self.http_method_not_allowed) # ←こいつの解説
handler =
の部分ですね。
まず、getattr()
という関数があります。
これは、公式ページに以下のような解説があります。
object の指名された属性の値を返します。 name は文字列でなくてはなりません。文字列がオブジェクトの属性の一つの名前であった場合、戻り値はその属性の値になります。例えば、 getattr(x, 'foobar') は x.foobar と等価です。指名された属性が存在しない場合、 default が与えられていればそれが返され、そうでない場合には AttributeError が送出されます。
組み込み関数 — Python 3.9.0 ドキュメント
https://docs.python.org/ja/3/library/functions.html#getattr
重要な部分はこの行です。
例えば、 getattr(x, 'foobar') は x.foobar と等価です。
getattr(ターゲットオブジェクト名, ターゲット関数名)
のように使っています。
以下は何を示すでしょうか。
getattr(self, request.method.lower())
request.method.lower()
は'get'
や'post'
等のHttpメソッドの小文字でした。
これらを組み合わせると、例えば、以下のようになります。
self.get()
self.post()
self
は自身を表します。
すなわち、自身が持つ関数のことです。
def get():
def post():
これがdef get()
やdef post()
でメソッドを定義できる理由です。
Httpメソッド名に関連する関数を呼び出しているのです。
したがって、Viewを継承する、もしくはViewを継承しているTemplateViewなどのクラスを継承していれば、
以下のようにHttpメソッドごとに関数を分けることができるのですね。😊
from django.views.generic import TemplateView
class HogeView(TemplateView): # Viewを継承しているTemplateViewなどのクラスを継承
template_name = 'hoge.html'
def get(): # httpメソッド名の関数(GET)が使える
pass # お好きな処理
def post(): # httpメソッド名の関数(POST)が使える
pass # お好きな処理
結論
Django ViewではHttpメソッドの関数が定義できます😊
def get():
# 処理
def post():
# 処理
以上!
ここまで読んでいただき、ありがとうございました。
あとがき
Djangoの継承関係把握は難しいです。
便利なサイトを紹介しておきます。
Django View Classの継承関係が見れたり、継承したメソッドが参照できます。
ご参考まで。
View -- Classy CBV
https://ccbv.co.uk/projects/Django/2.2/django.views.generic.base/View/