LoginSignup
2
2

More than 3 years have passed since last update.

Django ViewではHttpメソッド名の関数を定義することができる(get, post, put,patch,delete...)

Last updated at Posted at 2020-10-18

言いたいこと

Django ViewではHttpメソッドの関数が定義できます😊
定義した関数にHttpメソッドで振り分けられます。
私はGETでしかできないものだと思っていました。

views.py

def get():
    # 処理

def post():
    # 処理

該当メソッドの呼び出し場所

該当メソッドの呼び出し場所は以下にあります。
from django.views.generic import View

以下、メソッドの呼び出し場所の抜粋です。

django/views/generic/base.py
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行目を参照します。

django/views/generic/base.py
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'

続きを読んでいきます。

django/views/generic/base.py(再掲)
if request.method.lower() in self.http_method_names:

これらを.lower()で小文字にしています。

ここまでで、request.method.lower()が読み解けます。

Httpメソッド名が小文字で入っている。ということですね。
文字サイズアイコン3 (1).jpeg
Httpメソッド名が小文字で入っている。

これを踏まえて続きを見ましょう。

self.http_method_namesがあります。
これは以下のような変数が定義されています。

django/views/generic/base.py
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

Httpメソッド名が羅列されています。
getpostもありますね。

django/views/generic/base.py(再掲)
if request.method.lower() in self.http_method_names:

よって、1行目if文の結論としては

Httpメソッド名の場合にTrueとなる。

という結果になります。

要は、いつでもif文をTrueを通過するという認識です。

http_method_namesから'get''post'の記述を消せば、Falseになりますね。
ここらへんはカスタマイズ可能な作りになっているようです。

2行目- 定義された関数を呼び出す

django/views/generic/base.py
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メソッドごとに関数を分けることができるのですね。😊

views.py
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メソッドの関数が定義できます😊

views.py

def get():
    # 処理

def post():
    # 処理

以上!
ここまで読んでいただき、ありがとうございました。


あとがき

Djangoの継承関係把握は難しいです。
便利なサイトを紹介しておきます。
Django View Classの継承関係が見れたり、継承したメソッドが参照できます。
ご参考まで。

View -- Classy CBV
https://ccbv.co.uk/projects/Django/2.2/django.views.generic.base/View/

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2