Changes between Version 9 and Version 10 of ClassBasedViews
- Timestamp:
- Oct 4, 2010, 1:54:19 PM (14 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
ClassBasedViews
v9 v10 36 36 Alternatively, 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. 37 37 38 Example usage and view would be the same as shown below in " __call__and copy()".38 Example usage and view would be the same as shown below in "`__call__` and copy()". 39 39 40 40 Arguments for: … … 62 62 }}} 63 63 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.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. 65 65 66 66 No special handling is required in !UrlResolver -- the class instance is a callable, so it appears just like an existing view function. 67 67 68 68 Arguments 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). 71 71 72 ==== !__new!__() ====72 ==== !__new!__()` ==== 73 73 74 74 [http://github.com/fitzgen/django-class-based-views Implementation] … … 86 86 }}} 87 87 88 This approach is much the same as the !__copy!__() on !__call!__() approach, except that !__new!__()is used to create the new instance.88 This approach is much the same as the `__copy__()` on `__call__()` approach, except that `__new__()` is used to create the new instance. 89 89 90 90 Arguments 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 98 Example usage: 99 {{{ 100 url(r'^detail/author/(?P<pk>\d+)/$', views.AuthorDetail.as_view, name="author_detail"), 101 }}} 102 103 Example class: 104 {{{ 105 class AuthorView(View): 106 def GET(self, request, *args, **kwargs) 107 return self.render_to_response('author_list.html', {'authors': Author.objects.all()}) 108 }}} 109 110 This is very similar to the `__new__()` approach, except that we have to add a classmethod call to create the callable. 111 112 Arguments 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 93 115 94 116 ==== HTTPResponse subclassing ==== … … 109 131 Arguments against: 110 132 * 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. 112 134 113 135 ==== Recommendation ==== 114 136 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.137 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. 116 138 117 139 === Class Hierarchy ===