On Oct 3, 1:02 pm, Russell Keith-Magee <russ...@keith-magee.com>
wrote:
> On Sun, Oct 3, 2010 at 12:12 PM, Ian Lewis <ianmle...@gmail.com> wrote:
> > On Sun, Oct 3, 2010 at 11:20 AM, Russell Keith-Magee
> > <russ...@keith-magee.com> wrote:
> > While I'm in the "one singleton view instance is best" camp and think
> > that storing some state on the request and some on the view is a bit
> > gross, I understand Russell's arguments. New users are simply going to
> > save stuff on self no matter how much we complain, document etc. It's
> > simply a reality that likely can't be helped much.
>
> > Other frameworks seem have View/Handler instances per request, such as
> > appengine's webapp so there is some precedent for creating an instance
> > per request.
>
> >http://code.google.com/appengine/docs/python/gettingstarted/handlingf...
>
> I don't think you'll find any argument that having an instance per
> request would solve all the problems that this thread has described.
> The issue is how to declare a view that is able to be instantiated on
> a instance-per-request basis while simultaneously allowing decorators
> to be easily wrapped around that view.
>
> Yours,
> Russ Magee %-)

I haven't investigated the other solutions described in this
discussion, but the solution I proposed handles decorators just fine.
Furthermore, you can extend it to allow for decorators by
subclassing.

Initial code:

class BaseView(object):
    def __new__(cls, *args, **kwargs):
        obj = super(BaseView, cls).__new__(cls)
        # Call __init__ manually since it will not be called
        # after this method (since __new__ returns a HttpResponse
        # and not a BaseView subclass).
        obj.__init__(*args, **kwargs)
        return obj.view() # Or other name

class MyView(BaseView):
    def __init__(self, request):
        self.request = request
    def view(self):
        return HttpResponse(self.request.path)

urlpatterns = patterns("", ("^login_required_view/$",
login_required(MyView)))

This will create a view that requires login. We can extend this by
introducing a helper function class_decorator that takes a regular
decorator and turns it into a view class:

def class_decorator(decorator):
    class Cls(BaseView):
        def __new__(cls, *args, **kwargs):
            def view(*args, **kwargs):
                return super(Cls, cls).__new__(cls, *args, **kwargs)
            return decorator(view)(*args, **kwargs)
    return Cls

We can then create a LoginRequiredView for instance:
LoginRequiredView = class_decorator(login_required)

class MyView2(LoginRequiredView):
    def __init__(self, request):
        self.request = request
    def view(self):
        return HttpResponse(self.request.path)

MyView2 functions like login_required(MyView). We can also chain
decorators by multiple inheritance.
AUsersView = class_decorator(user_passes_test(lambda u: "a" in
u.username.lower()))

class MyView3(LoginRequiredView, AUsersView):
    """
    View that requires users to be logged in and
    have a username that contain an 'a'.
    """
    def __init__(self, request):
        self.request = request
    def view(self):
        return HttpResponse(self.request.path)


Best regards,
André Eriksson

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

Reply via email to