ruk·si

🍡 Django
Views

Updated at 2018-04-04 02:49

Django view is a callable that takes a request and returns a response.

from django.http import HttpResponse

def my_view(request):
    return HttpResponse('result')

Views frequently render a template.

from django.shortcuts import render

def about_view(request):
    return render(request, 'about.html')

Django views can be class-based. Then the class ancestry must contain View base class.

from django.views.generic import TemplateView

TemplateView.as_view(template_name='about.html')

# or the same but as a fully defined class...

class AboutView(TemplateView):
    template_name = 'about.html'

AboutView.as_view()

View class lifecycle starts with dispatch and ends in HTTP response.

COMMON LIFECYCLE OVERVIEW:
  > Django calls dispatch on the view class
    > dispatch with optional HTTP method selection
      > HTTP method function (get, post, etc.) on the view class
        > returns HttpResponse
          > Django uses the HttpResponse as the base for the response
class View(object):
    # ...
    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)
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)
    # ...

# where the dispatch routes it back up to less abstract class that
# defines different HTTP method responses, e.g.

class TemplateView(TemplateResponseMixin, ContextMixin, View):
    # ...
    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)
        return self.render_to_response(context)
    # ...

# these HTTP method functions return an instance of HttpResponse

return HttpResponse(status=405, content='POST only')

# HttpResponse defines content, content type, status, headers, cookies etc.
# all that is required for serialization and sending the response

class HttpResponse(HttpResponseBase):
    # ...
    def __init__(self, content=b'', *args, **kwargs):
        super(HttpResponse, self).__init__(*args, **kwargs)
        self.content = content
    # ...

Here are some commonly extended views:

  • django.views.View: url.py linking and basic http method handling.
  • generic.TemplateView: renders template named template_name.
  • generic.DetailView: expects <app name>/<model name>_detail.html template and provides model of type model with primary key of pk in the url.
  • generic.ListView: expects <app name>/<model name>_list.html template and provides context_object_name queryset provided by get_queryset() method or queryset attribute.
  • generic.RedirectView: TODO
  • generic.FormView: TODO
  • generic.CreateView: TODO
  • generic.UpdateView: TODO
  • generic.DeleteView: TODO
  • generic.ArchiveIndexView: TODO
  • generic.YearArchiveView: TODO
  • generic.MonthArchiveView: TODO
  • generic.WeekArchiveView: TODO
  • generic.DayArchiveView: TODO
  • generic.TodayArchiveView: TODO
  • generic.DateDetailView: TODO

Some generic views can also be used as functions:

from django.conf.urls import url
from django.views.generic import TemplateView

urlpatterns = [
    url(r'^about/$', TemplateView.as_view(template_name="about.html")),
]

# compared to normal usage:
from django.conf.urls import url
from someapp.views import AboutView

urlpatterns = [
    url(r'^about/$', AboutView.as_view()),
]

Interesting attributes and methods that can be overwitten:

  • template_name: which template to render.
  • get_context_data(): the context when rendering the template.
  • render_to_response(): how template rendering happens, usually not customized.
  • get(): what GET request returns, usually HttpResponse.
  • post(): what POST request returns, usually HttpResponseRedirect or HttpResponse.
  • head(): what HEAD request returns, usually empty HttpResponse with headers.

TODO: https://docs.djangoproject.com/en/1.10/topics/class-based-views/

Mixins

If you would like to inherit from multiple generic views; inherit from View and add other views as mixins.

For example, here is how TemplateView is defined:

class TemplateView(TemplateResponseMixin, ContextMixin, View):
    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)
        return self.render_to_response(context)

Mixin list:

  • TemplateResponseMixin: A mixin that can be used to render a template.
  • ContextMixin: Provides method for template context definition.
  • SingleObjectMixin: Provides a mechanism for looking up an object associated with the current HTTP request.
  • SingleObjectTemplateResponseMixin: A mixin class that performs template-based response rendering for views that operate upon a single object instance.
  • MultipleObjectMixin: A mixin that can be used to lookup a list of objects associated with the current HTTP request.
  • MultipleObjectTemplateResponseMixin: A mixin class that performs template-based response rendering for views that operate upon a list of object instances.
  • FormMixin: A mixin class that provides facilities for creating and displaying forms.
  • ModelFormMixin: A form mixin that works on ModelForms, rather than a standalone form.
  • ProcessFormView: A mixin that provides basic HTTP GET and POST workflow.
  • DeletionMixin: Enables handling of the DELETE http action.
  • YearMixin: A mixin that can be used to retrieve and provide parsing information for a year component of a date.
  • MonthMixin: The same as previous but month.
  • DayMixin: The same as previous but day.
  • WeekMixin: The same as previous but week.
  • DateMixin: A mixin class providing common behavior for all date-based views.
  • BaseDateListView: A base class that provides common behavior for all date-based views.

View Decorators

Common or frequently changing functionality between views can be added to decorators.

decorators = [never_cache, login_required]

@method_decorator(decorators, name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'

@method_decorator(never_cache, name='dispatch')
@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'

Sources