0
1

More than 3 years have passed since last update.

DjangoーCBVのソースコード分析してみる。

Posted at

 Views層でFBVとCBVを書く時、なぜ同じ結果が得られるかの疑問はないでしょうか。そしてUrls層でルーティングを設定する場合もCBVとFBVの書き方が変わりますよね? その原因をソースコードに合わせ、見ていきたいと思っています。

 CBVの根本的なところに入るための入口はどこにあるか、そしてどの流れでgetやpostを実行するのかを見てみましょう!

入口

path('books1/', views.Books.as_view())

as_view()を入り口とし、後ろのソースコードを追跡します。
image.png

はい、では、@classonlymethodはviews.Books.as_view()と書く理由で、クラスメソッドのことです。

as_viewメソッドはviewが戻り値になり、このviewは実際にas_view内部の関数のことを指しています。

view関数の戻り値はdispatch関数なので、次はdispatchを追跡します。

ここで、ちょっと補足しますが、pythonの継承関係について。このdispatchの例で言うと、dispatchを実行したい場合、最初はクラスのobject(インスタンス)から探します、そしてobjectが所属したclass、って継承されたclassの流れでdispatchを探します。今回はobjectにdispatch方法がないため、自然にViewクラスのdispatch方法を実行します。*

dispatch

   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)

これはViewクラスのdispatch方法です。引数について、selfはobjectのこと、requestはurlsで与えられたrequestのことです。

if文のところから見てみます。request.method.lower()は例えばPOSTやGETを小文字化するため、self.http_method_namesはなんやろ??

実はViewクラスで定義され、

http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

となります。

次に、if分が成立したら、ようするにrequest methodがこのリストに入っているのであれば、次を実行します。

handler = getattr(self, request.method.lower(), self.http_method_not_allowed)

getattrを使って、self(objectのこと)の中に、POSTやGETを小文字化した方法はあるかどうか。あるの場合はhandler変数に与え、なかった場合はself.http_method_not_allowedがhanlder変数に与えます(self.http_method_not_allowedはデフォルト値と考えてもいいだと思います))。

そしてdispatch方法に戻り、戻り値をチェックしてください。

return handler(request, *args, **kwargs)

なんと!思った以上より分かりやすくて、単純にhandlerがreturnされただけ!

まとめると、as_viewから入り、dispatch方法を実行し、帰ってくるのはgetやpost方法になります。

まとめ

 CBVは非常に重要です、特にDjango RestFrameWork上に大きいな役割を果たしています。また、DRFは実際、DjangoのViewを継承されていますので、DRFの理解を深まるためにはCBVの実行の流れも理解する必要があるだと思っています。

 それほど詳しい説明ではないですが、最後まで見ていただきありがとうございました。

0
1
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
0
1