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

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

```python:views.py

def get():
    # 処理

def post():
    # 処理
```

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

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

```python: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行目を参照します。

```python: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 メソッドを表す文字列です。必ず大文字になります。 

```python
if request.method == 'GET':
    do_something()
elif request.method == 'POST':
    do_something_else()
```

すなわち、`request.method`には**HTTPメソッド名**が入ることになります😊
メソッド名は大文字で渡されています。

例えば、以下のようなものですね。
`'GET'`
`'POST'`
`'PUT'`

続きを読んでいきます。

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

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


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

**Httpメソッド名が小文字で入っている。**ということですね。
![文字サイズアイコン3 (1).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384142/a22a7178-c674-9828-ffd7-4abc2df5abec.jpeg)
Httpメソッド名が小文字で入っている。

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

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

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

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

```python: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行目- 定義された関数を呼び出す
```python: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(ターゲットオブジェクト名, ターゲット関数名)`のように使っています。
以下は何を示すでしょうか。

```python
getattr(self, request.method.lower())
```

`request.method.lower()`は`'get'`や`'post'`等のHttpメソッドの小文字でした。

これらを組み合わせると、例えば、以下のようになります。
`self.get()`
`self.post()`

`self`は自身を表します。
すなわち、自身が持つ関数のことです。

```python

def get():
    
def post():
```


これが`def get()`や`def post()`でメソッドを定義できる理由です。

Httpメソッド名に関連する関数を呼び出しているのです。

したがって、**Viewを継承する**、もしくは**Viewを継承しているTemplateViewなどのクラスを継承**していれば、
以下のようにHttpメソッドごとに関数を分けることができるのですね。😊

```python: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メソッドの関数**が定義できます😊

```python: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/