LoginSignup
2
3

More than 3 years have passed since last update.

[Django]as_view()のメモ

Posted at

[Django]as_view()のメモ

初学者の学習メモ記事になります。
Djangoの汎用ビューで使われるas_view()がどのように動くかをメモ。
ここを理解できれば、汎用ビューのベースとなるViewを理解し、実装できるかなと思います。

as_view()の使用例

Djangoでurls.pyファイルへルーティングを書く際に、汎用ビューを利用する場合に記載します。
以下が使用例です。

urls.py
from django.urls import path
from . import views

app_name = 'recipe'

urlpatterns = [
    path('', views.[クラス名].as_view(), name='index'),
]
views.py
from django.views.generic import TemplateView

class RecipeListView(TemplateView):
    """
    テンプレートビュークラス
    """
    template_name = '[アプリケーション名]/index.html'

この実装によって、ルートパスでアクセスしたページにindex.htmlの内容が表示されます。

as_view()って何している?

上記の実装では「TemplateView」を継承し汎用ビューを実装していましたが、「TemplateView」は「View」を継承しています。
以下が「View」のソースです。(説明部分のみ抜粋)

django/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__(self, **kwargs):
        """
        Constructor. Called in the URLconf; can contain helpful extra
        keyword arguments, and other things.
        """
        # Go through keyword arguments, and either save their values to our
        # instance, or raise an error.
        for key, value in kwargs.items():
            setattr(self, key, value)

    @classonlymethod
    def as_view(cls, **initkwargs):
        """Main entry point for a request-response process."""
        for key in initkwargs:
            if key in cls.http_method_names:
                raise TypeError(
                    'The method name %s is not accepted as a keyword argument '
                    'to %s().' % (key, cls.__name__)
                )
            if not hasattr(cls, key):
                raise TypeError("%s() received an invalid keyword %r. as_view "
                                "only accepts arguments that are already "
                                "attributes of the class." % (cls.__name__, key))

        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            self.setup(request, *args, **kwargs)
            if not hasattr(self, 'request'):
                raise AttributeError(
                    "%s instance has no 'request' attribute. Did you override "
                    "setup() and forget to call super()?" % cls.__name__
                )
            return self.dispatch(request, *args, **kwargs)
        view.view_class = cls
        view.view_initkwargs = initkwargs

        # take name and docstring from class
        update_wrapper(view, cls, updated=())

        # and possible attributes set by decorators
        # like csrf_exempt from dispatch
        update_wrapper(view, cls.dispatch, assigned=())
        return view
            :
            :
    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)

            :
            :

as_view()はdippatchメソッドを戻り値として返している。
dippatchメソッドは、http_method_namesで定義されたメソッド(getやpost)を呼び出すように実装されている。
なので、as_view()は、クライアントから発火したリクエストに対して、汎用ビューのget()やpost()を呼び出す。

ちなみに「TemplateView」のget()は以下の内容になっており、戻り値としてrender_to_responseを返している。

django/django/views/generic/base.py
class TemplateView(TemplateResponseMixin, ContextMixin, View):
    """Render a template."""
    def get(self, request, *args, **kwargs):
        # RemovedInDjango40Warning: when the deprecation ends, replace with:
        #   context = self.get_context_data()
        context_kwargs = _wrap_url_kwargs_with_deprecation_warning(kwargs)
        context = self.get_context_data(**context_kwargs)
        return self.render_to_response(context)

以上。

参考

Django汎用クラスビューの実装を理解する
Django base.py

2
3
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
3