Changes between Version 9 and Version 10 of ClassBasedViews


Ignore:
Timestamp:
Oct 4, 2010, 1:54:19 PM (14 years ago)
Author:
Luke Plant
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • ClassBasedViews

    v9 v10  
    3636Alternatively, override `__getattr__/__setattr__` to access `self.request.state` under the hood while on the surface it looks as if the state is stored on the view instance.
    3737
    38 Example usage and view would be the same as shown below in "__call__ and copy()".
     38Example usage and view would be the same as shown below in "`__call__` and copy()".
    3939
    4040Arguments for:
     
    6262}}}
    6363
    64 This approach proposes that an class instance be placed in urls.py; the instance has a !__call!__() method, and when that method is invoked, it takes a shallow copy of the instance defined in urls.py, and returns the result of invoking the request method (e.g., GET()). This achieves thread safety by ensuring that every request is given a clean instance on the view class to work on.
     64This approach proposes that an class instance be placed in urls.py; the instance has a `__call__()` method, and when that method is invoked, it takes a shallow copy of the instance defined in urls.py, and returns the result of invoking the request method (e.g., GET()). This achieves thread safety by ensuring that every request is given a clean instance on the view class to work on.
    6565
    6666No special handling is required in !UrlResolver -- the class instance is a callable, so it appears just like an existing view function.
    6767
    6868Arguments against:
    69  * The "copy on !__call!__()" approach is a little messy. Normal Python idiom wouldn't lead users to expect that !__call!__() would cause a copy to be created.
    70  * The abstraction of the copy-on-call can leak in surprising ways. Some users will try to set up state using an !__init!__ method (common practice). If any of the state they attach to self in !__init!__ is mutable (list, dict, object, etc) and they mutate it in the view, this will fail (but not immediately, or in obvious ways).
     69 * The "copy on `__call__()`" approach is a little messy. Normal Python idiom wouldn't lead users to expect that `__call__()` would cause a copy to be created.
     70 * The abstraction of the copy-on-call can leak in surprising ways. Some users will try to set up state using an `__init__` method (common practice). If any of the state they attach to self in `__init__` is mutable (list, dict, object, etc) and they mutate it in the view, this will fail (but not immediately, or in obvious ways).
    7171
    72 ==== !__new!__() ====
     72==== !__new!__()` ====
    7373
    7474[http://github.com/fitzgen/django-class-based-views Implementation]
     
    8686}}}
    8787
    88 This approach is much the same as the !__copy!__() on !__call!__() approach, except that !__new!__() is used to create the new instance.
     88This approach is much the same as the `__copy__()` on `__call__()` approach, except that `__new__()` is used to create the new instance.
    8989
    9090Arguments against:
    91  * You can't use arguments to __init__() to instantiate a class view
    92  * x = !AuthorView() returns x as a HTTPResponse, not an !AuthorView instance. This violates expectations of normal class usage.
     91 * You can't use arguments to `__init__()` to instantiate a class view (although you can add a `configure` class method to replace this usage)
     92 * `x = AuthorView()` returns x as a HTTPResponse, not an `AuthorView` instance. This violates expectations of normal class usage.
     93
     94==== classmethod ====
     95
     96[http://github.com/spookylukey/django-class-based-views Implementation]
     97
     98Example usage:
     99{{{
     100    url(r'^detail/author/(?P<pk>\d+)/$', views.AuthorDetail.as_view, name="author_detail"),
     101}}}
     102
     103Example class:
     104{{{
     105class AuthorView(View):
     106    def GET(self, request, *args, **kwargs)
     107        return self.render_to_response('author_list.html', {'authors': Author.objects.all()})
     108}}}
     109
     110This is very similar to the `__new__()` approach, except that we have to add a classmethod call to create the callable.
     111
     112Arguments against:
     113 * You can't use arguments to `__init__()` to instantiate a class view (although you can add a `configure` class method to replace this usage)
     114 * The URLconf is slightly more verbose
    93115
    94116==== HTTPResponse subclassing ====
     
    109131Arguments against:
    110132 * Requires special cases in !UrlResolver which almost inevitably involve isinstance(!ViewClass) or some analog.
    111  * Decorators become extremely difficult to use; wrapping methods or __call__ on an uninstantiated class is hard.
     133 * Decorators become extremely difficult to use; wrapping methods or `__call__` on an uninstantiated class is hard.
    112134
    113135==== Recommendation ====
    114136
    115 Based on these discussions, plus in-person discussions at !DjangoCon.eu,  !__copy!__() on !__call!__() appears to be a slight front runner, with !__new!__() as a close runner up.
     137Based on these discussions, plus in-person discussions at !DjangoCon.eu,  `__copy__()` on `__call__()` appears to be a slight front runner, with `__new__()` as a close runner up.
    116138
    117139=== Class Hierarchy ===
Back to Top