Hello

As you may know, current class-based views have been criticized for
their complexity.

Their design is a bit convoluted and difficult to understand by the
average view author and therefore any work made with them may hide
sneaky bugs.

On top of that, it's difficult to apply common decorators to them. The
recommended approach seems to be to apply them to the dispatch()
method. But this requires overriding that method even when the base
dispatch strategy is otherwise adequate, and converting the decorators
with method_decorator(). This is ugly and is only a partial solution,
as method_decorator() doesn't currently support decorators with
arguments, such as @user_passes_test(a_test).

All this is unfortunate, because there is a clear need for a simple,
Pythonic object-oriented approach to view authoring, to achieve
separation of concerns and code reuse. Dispatching by http method (one
of the basic features of class-based views) is also a growing need, in
the world of AJAX and REST-based web applications.

I have attached my proposal for a slight change in the design of class-
based views. It is similar in purpose to the existing ones, but much
simpler to use and to extend.

Examples speak louder than words:

--- urls.py ---

urlpatterns = patterns('',
    url(r'^(\d)+/$', views.Article),
)

--- views.py ---

@login_required
class Article(View):

    def __init__(self, request, pk):
        super(Article, self).__init__(request, pk)
        self.pk = pk

    def get(self):
        article = get_object_or_404(Article, pk=self.pk)
        return render_to_response('hello.html', {'article': article})

    def post(self):
        return HttpResponse('You posted something but I threw it
away.')

---

Points of note:
 - the usage in urls.py is now indistinguishable from regular views;
 - subclasses may extend __init__ to make use of request parameters;
 - the dispatch logic, based on http method, is hidden in the base
class;
 - standard decorators may be simply applied to the class (Python >=
2.6)

Here is the View base class: http://dpaste.com/hold/665528/
It's very simple, even shorter than the existing implementation.

I haven't taken the time to translate the whole django.views.generic
package to this new design, but I will do so shortly, assuming I get
some kind of positive feedback. The existing functionality (the
various generic views and mixins) should be fairly easy to port to the
new design.

This is a slightly different design, so there are bound to be a few
incompatibilities. For example in my code the dispatched methods (get,
post...) don't receive the request object and parameters, because they
were already passed to __init__ and it wouldn't make sense to pass
them again.

I'm not familiar with Django practices about backwards compatibility.
If it's really important not to break old code, I guess the new style
classes could be made to keep the same interface as existing ones,
including a dummy as_view() method. But it would pollute the code with
old cruft. Or they could be implemented in a new package. I need
further directions on this issue.

-Tobia

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to