[Django]as_view()のメモ
初学者の学習メモ記事になります。
Djangoの汎用ビューで使われるas_view()がどのように動くかをメモ。
ここを理解できれば、汎用ビューのベースとなるViewを理解し、実装できるかなと思います。
as_view()の使用例
Djangoでurls.pyファイルへルーティングを書く際に、汎用ビューを利用する場合に記載します。
以下が使用例です。
from django.urls import path
from . import views
app_name = 'recipe'
urlpatterns = [
path('', views.[クラス名].as_view(), name='index'),
]
from django.views.generic import TemplateView
class RecipeListView(TemplateView):
"""
テンプレートビュークラス
"""
template_name = '[アプリケーション名]/index.html'
この実装によって、ルートパスでアクセスしたページにindex.htmlの内容が表示されます。
as_view()って何している?
上記の実装では「TemplateView」を継承し汎用ビューを実装していましたが、「TemplateView」は「View」を継承しています。
以下が「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__(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を返している。
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)
以上。