Ticket #16963: relocate_view_class-2.diff

File relocate_view_class-2.diff, 13.8 KB (added by Preston Holmes, 13 years ago)
  • new file django/views/base.py

    diff --git a/django/views/base.py b/django/views/base.py
    new file mode 100644
    index 0000000..924e0d4
    - +  
     1from functools import update_wrapper
     2
     3from django import http
     4from django.utils.decorators import classonlymethod
     5from django.utils.log import getLogger
     6
     7logger = getLogger('django.request')
     8
     9class View(object):
     10    """
     11    Intentionally simple parent class for all class-based views. Only
     12    implements dispatch-by-method and simple sanity checking.
     13    """
     14
     15    http_method_names = ['get', 'post', 'put', 'delete', 'head', 'options', 'trace']
     16
     17    def __init__(self, **kwargs):
     18        """
     19        Constructor. Called in the URLconf; can contain helpful extra
     20        keyword arguments, and other things.
     21        """
     22        # Go through keyword arguments, and either save their values to our
     23        # instance, or raise an error.
     24        for key, value in kwargs.iteritems():
     25            setattr(self, key, value)
     26
     27    @classonlymethod
     28    def as_view(cls, **initkwargs):
     29        """
     30        Main entry point for a request-response process.
     31        """
     32        # sanitize keyword arguments
     33        for key in initkwargs:
     34            if key in cls.http_method_names:
     35                raise TypeError(u"You tried to pass in the %s method name as a "
     36                                u"keyword argument to %s(). Don't do that."
     37                                % (key, cls.__name__))
     38            if not hasattr(cls, key):
     39                raise TypeError(u"%s() received an invalid keyword %r" % (
     40                    cls.__name__, key))
     41
     42        def view(request, *args, **kwargs):
     43            self = cls(**initkwargs)
     44            return self.dispatch(request, *args, **kwargs)
     45
     46        # take name and docstring from class
     47        update_wrapper(view, cls, updated=())
     48
     49        # and possible attributes set by decorators
     50        # like csrf_exempt from dispatch
     51        update_wrapper(view, cls.dispatch, assigned=())
     52        return view
     53
     54    def dispatch(self, request, *args, **kwargs):
     55        # Try to dispatch to the right method; if a method doesn't exist,
     56        # defer to the error handler. Also defer to the error handler if the
     57        # request method isn't on the approved list.
     58        if request.method.lower() in self.http_method_names:
     59            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
     60        else:
     61            handler = self.http_method_not_allowed
     62        self.request = request
     63        self.args = args
     64        self.kwargs = kwargs
     65        return handler(request, *args, **kwargs)
     66
     67    def http_method_not_allowed(self, request, *args, **kwargs):
     68        allowed_methods = [m for m in self.http_method_names if hasattr(self, m)]
     69        logger.warning('Method Not Allowed (%s): %s' % (request.method, request.path),
     70            extra={
     71                'status_code': 405,
     72                'request': self.request
     73            }
     74        )
     75        return http.HttpResponseNotAllowed(allowed_methods)
     76
     77    def head(self, *args, **kwargs):
     78        return self.get(*args, **kwargs)
     79
     80
  • django/views/generic/__init__.py

    diff --git a/django/views/generic/__init__.py b/django/views/generic/__init__.py
    index 1a98067..900d039 100644
    a b  
    1 from django.views.generic.base import View, TemplateView, RedirectView
     1from django.views.base import View
     2from django.views.generic.base import TemplateView, RedirectView
    23from django.views.generic.dates import (ArchiveIndexView, YearArchiveView, MonthArchiveView,
    34                                     WeekArchiveView, DayArchiveView, TodayArchiveView,
    45                                     DateDetailView)
  • django/views/generic/base.py

    diff --git a/django/views/generic/base.py b/django/views/generic/base.py
    index f2d4950..90e321d 100644
    a b  
    1 from functools import update_wrapper
    21from django import http
    32from django.core.exceptions import ImproperlyConfigured
    43from django.template.response import TemplateResponse
    54from django.utils.log import getLogger
    6 from django.utils.decorators import classonlymethod
     5from django.views.base import View
    76
    87logger = getLogger('django.request')
    98
    109
    11 class View(object):
    12     """
    13     Intentionally simple parent class for all views. Only implements
    14     dispatch-by-method and simple sanity checking.
    15     """
    16 
    17     http_method_names = ['get', 'post', 'put', 'delete', 'head', 'options', 'trace']
    18 
    19     def __init__(self, **kwargs):
    20         """
    21         Constructor. Called in the URLconf; can contain helpful extra
    22         keyword arguments, and other things.
    23         """
    24         # Go through keyword arguments, and either save their values to our
    25         # instance, or raise an error.
    26         for key, value in kwargs.iteritems():
    27             setattr(self, key, value)
    28 
    29     @classonlymethod
    30     def as_view(cls, **initkwargs):
    31         """
    32         Main entry point for a request-response process.
    33         """
    34         # sanitize keyword arguments
    35         for key in initkwargs:
    36             if key in cls.http_method_names:
    37                 raise TypeError(u"You tried to pass in the %s method name as a "
    38                                 u"keyword argument to %s(). Don't do that."
    39                                 % (key, cls.__name__))
    40             if not hasattr(cls, key):
    41                 raise TypeError(u"%s() received an invalid keyword %r" % (
    42                     cls.__name__, key))
    43 
    44         def view(request, *args, **kwargs):
    45             self = cls(**initkwargs)
    46             return self.dispatch(request, *args, **kwargs)
    47 
    48         # take name and docstring from class
    49         update_wrapper(view, cls, updated=())
    50 
    51         # and possible attributes set by decorators
    52         # like csrf_exempt from dispatch
    53         update_wrapper(view, cls.dispatch, assigned=())
    54         return view
    55 
    56     def dispatch(self, request, *args, **kwargs):
    57         # Try to dispatch to the right method; if a method doesn't exist,
    58         # defer to the error handler. Also defer to the error handler if the
    59         # request method isn't on the approved list.
    60         if request.method.lower() in self.http_method_names:
    61             handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    62         else:
    63             handler = self.http_method_not_allowed
    64         self.request = request
    65         self.args = args
    66         self.kwargs = kwargs
    67         return handler(request, *args, **kwargs)
    68 
    69     def http_method_not_allowed(self, request, *args, **kwargs):
    70         allowed_methods = [m for m in self.http_method_names if hasattr(self, m)]
    71         logger.warning('Method Not Allowed (%s): %s' % (request.method, request.path),
    72             extra={
    73                 'status_code': 405,
    74                 'request': self.request
    75             }
    76         )
    77         return http.HttpResponseNotAllowed(allowed_methods)
    78 
    79     def head(self, *args, **kwargs):
    80         return self.get(*args, **kwargs)
    81 
    82 
    8310class TemplateResponseMixin(object):
    8411    """
    8512    A mixin that can be used to render a template.
  • django/views/generic/dates.py

    diff --git a/django/views/generic/dates.py b/django/views/generic/dates.py
    index c10db30..b9661fa 100644
    a b from django.core.exceptions import ImproperlyConfigured  
    44from django.http import Http404
    55from django.utils.encoding import force_unicode
    66from django.utils.translation import ugettext as _
    7 from django.views.generic.base import View
     7from django.views.base import View
    88from django.views.generic.detail import BaseDetailView, SingleObjectTemplateResponseMixin
    99from django.views.generic.list import MultipleObjectMixin, MultipleObjectTemplateResponseMixin
    1010
  • django/views/generic/detail.py

    diff --git a/django/views/generic/detail.py b/django/views/generic/detail.py
    index ab21573..eccbf2e 100644
    a b from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist  
    22from django.http import Http404
    33from django.utils.encoding import smart_str
    44from django.utils.translation import ugettext as _
    5 from django.views.generic.base import TemplateResponseMixin, View
     5from django.views.base import View
     6from django.views.generic.base import TemplateResponseMixin
    67
    78
    89class SingleObjectMixin(object):
  • django/views/generic/edit.py

    diff --git a/django/views/generic/edit.py b/django/views/generic/edit.py
    index 3cade52..4ab01d0 100644
    a b  
    11from django.forms import models as model_forms
    22from django.core.exceptions import ImproperlyConfigured
    33from django.http import HttpResponseRedirect
    4 from django.views.generic.base import TemplateResponseMixin, View
     4from django.views.base import View
     5from django.views.generic.base import TemplateResponseMixin
    56from django.views.generic.detail import (SingleObjectMixin,
    67                        SingleObjectTemplateResponseMixin, BaseDetailView)
    78
  • django/views/generic/list.py

    diff --git a/django/views/generic/list.py b/django/views/generic/list.py
    index 9797356..6d04ac2 100644
    a b from django.core.exceptions import ImproperlyConfigured  
    33from django.http import Http404
    44from django.utils.encoding import smart_str
    55from django.utils.translation import ugettext as _
    6 from django.views.generic.base import TemplateResponseMixin, View
     6from django.views.base import View
     7from django.views.generic.base import TemplateResponseMixin
    78
    89
    910class MultipleObjectMixin(object):
  • docs/ref/class-based-views.txt

    diff --git a/docs/ref/class-based-views.txt b/docs/ref/class-based-views.txt
    index 5f1340b..4ec9cf5 100644
    a b usable generic views.  
    4141For example, the :class:`~django.views.generic.base.detail.DetailView`
    4242is composed from:
    4343
    44     * :class:`~django.db.views.generic.base.View`, which provides the
     44    * :class:`~django.views.base.View`, which provides the
    4545      basic class-based behavior
    46     * :class:`~django.db.views.generic.detail.SingleObjectMixin`, which
     46    * :class:`~django.views.generic.detail.SingleObjectMixin`, which
    4747      provides the utilities for retrieving and displaying a single object
    48     * :class:`~django.db.views.generic.detail.SingleObjectTemplateResponseMixin`,
     48    * :class:`~django.views.generic.detail.SingleObjectTemplateResponseMixin`,
    4949      which provides the tools for rendering a single object into a
    5050      template-based response.
    5151
    BaseDateListView  
    817817        See :meth:`~django.db.models.query.QuerySet.dates()` for the
    818818        ways that the ``date_type`` argument can be used.
    819819
     820Class-based view base class
     821===========================
    820822
    821 Generic views
    822 =============
    823 
    824 Simple generic views
    825 --------------------
    826 
    827 .. currentmodule:: django.views.generic.base
     823.. currentmodule:: django.views.base
    828824
    829825View
    830826~~~~
    831827.. class:: View()
    832828
    833     The master class-based base view. All other generic class-based views
     829    The master class-based base view. All generic class-based views
    834830    inherit from this base class.
    835831
    836     Each request served by a :class:`~django.views.generic.base.View` has an
     832    Each request served by a :class:`~django.views.base.View` has an
    837833    independent state; therefore, it is safe to store state variables on the
    838834    instance (i.e., ``self.foo = 3`` is a thread-safe operation).
    839835
    View  
    879875        The default implementation returns ``HttpResponseNotAllowed`` with list
    880876        of allowed methods in plain text.
    881877
     878Generic views
     879=============
     880
     881Simple generic views
     882--------------------
     883
     884.. currentmodule:: django.views.generic.base
     885
    882886TemplateView
    883887~~~~~~~~~~~~
    884888.. class:: TemplateView()
  • docs/topics/class-based-views.txt

    diff --git a/docs/topics/class-based-views.txt b/docs/topics/class-based-views.txt
    index 62368fa..e44ef57 100644
    a b Decorating in URLconf  
    566566---------------------
    567567
    568568The simplest way of decorating class-based views is to decorate the
    569 result of the :meth:`~django.views.generic.base.View.as_view` method.
     569result of the :meth:`~django.views.base.View.as_view` method.
    570570The easiest place to do this is in the URLconf where you deploy your
    571571view::
    572572
    Decorating the class  
    589589
    590590To decorate every instance of a class-based view, you need to decorate
    591591the class definition itself. To do this you apply the decorator to the
    592 :meth:`~django.views.generic.base.View.dispatch` method of the class.
     592:meth:`~django.views.base.View.dispatch` method of the class.
    593593
    594594A method on a class isn't quite the same as a standalone function, so
    595595you can't just apply a function decorator to the method -- you need to
  • tests/regressiontests/generic_views/base.py

    diff --git a/tests/regressiontests/generic_views/base.py b/tests/regressiontests/generic_views/base.py
    index 40490a4..58241e3 100644
    a b import unittest  
    44from django.core.exceptions import ImproperlyConfigured
    55from django.http import HttpResponse
    66from django.test import TestCase, RequestFactory
    7 from django.views.generic import View, TemplateView, RedirectView
     7from django.views.base import View
     8from django.views.generic import TemplateView, RedirectView
    89
    910
    1011class SimpleView(View):
  • tests/regressiontests/special_headers/views.py

    diff --git a/tests/regressiontests/special_headers/views.py b/tests/regressiontests/special_headers/views.py
    index ce94036..91a8b5b 100644
    a b  
    11# -*- coding:utf-8 -*-
    22from django.http import HttpResponse
    33from django.utils.decorators import decorator_from_middleware
    4 from django.views.generic import View
     4from django.views.base import View
    55from django.middleware.doc import XViewMiddleware
    66
    77xview_dec = decorator_from_middleware(XViewMiddleware)
Back to Top