Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Class based views: A standard hook for http-method-independent code
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  Messages 26 - 47 of 47 - Collapse all  -  Translate all to Translated (View all originals) < Older 
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Diederik van der Boor  
View profile  
 More options Nov 8 2012, 7:42 am
From: Diederik van der Boor <vdb...@gmail.com>
Date: Thu, 8 Nov 2012 13:42:03 +0100
Local: Thurs, Nov 8 2012 7:42 am
Subject: Re: Class based views: A standard hook for http-method-independent code

Op 7 nov. 2012, om 17:49 heeft Aaron Merriam het volgende geschreven:

> I wanted to post and modified version of a gist posted earlier in this thread.

> https://gist.github.com/4032482

> I originally implemented the original structure of having an `init` hook which was called between setting request, args, and kwargs, but i quickly found that I had a few situations where I needed to fully hijack the response rather than just checking a permission or throwing an exception.  

> I'm curious what others think of this.

I really like the idea of this implementation. I do like to see some examples associated with this feature,
and I think that would be valuable for everyone :)

I still think such init() or initial() feature would be beneficial for CBV's,
and actually reduce complexity (cc Russell here) but the examples make the difference here :)

For example, how would this be written without a init method?

class PhotoListView(TabbedListView):
    """
    Contents of an photo album; a list of photo's.
    """
    model = Photo

    template_name = "photoalbum_album.html"
    permission_class = permissions.PhotoAlbumViewPermission

    def init(self):
        super(PhotoListView, self).init()  # runs permission checks
        self.photoalbum = get_object_or_404(PhotoAlbum, pk=self.kwargs['pk'])  # parent object that filters the list

    def get_queryset(self):
        return super(PhotoListView, self).get_queryset().in_album(self.photoalbum)

    def get_context_data(self, **kwargs):
        context = super(PhotoListView, self).get_context_data(**kwargs)
        context['photoalbum'] = self.photoalbum
        context['can_delete'] = self.is_authorized_for(PhotoDeleteView)
        return context

Off course you can, but I'd like to initiate that challenge to get a good view of the complexity trade-offs here.

Greetings,

Diederik


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Russell Keith-Magee  
View profile  
 More options Nov 8 2012, 6:29 pm
From: Russell Keith-Magee <russ...@keith-magee.com>
Date: Fri, 9 Nov 2012 07:29:08 +0800
Local: Thurs, Nov 8 2012 6:29 pm
Subject: Re: Class based views: A standard hook for http-method-independent code

On Thu, Nov 8, 2012 at 8:42 PM, Diederik van der Boor <vdb...@gmail.com>wrote:

I'd like to offer an answer here, but it isn't clear to me at all what this
is trying to do (or rather, what ordering dependencies are assumed to exist.

For some reason, init() is apparently doing permission checks by default --
but it isn't clear what causes those permission checks to be done; it also
isn't clear how you can do permission checks before you've actually got an
object to work with.

As far as setting self.photoset -- that could be done in dispatch(), or in
get(), or possibly even in get_queryset().

In short, there isn't enough detail here for me to pass comment.

Yours,
Russ Magee %-)


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Aaron Merriam  
View profile  
 More options Nov 9 2012, 12:05 am
From: Aaron Merriam <aaronmerr...@gmail.com>
Date: Thu, 8 Nov 2012 21:05:43 -0800 (PST)
Local: Fri, Nov 9 2012 12:05 am
Subject: Re: Class based views: A standard hook for http-method-independent code

Without setting request, args, and kwargs on on the view instance (which is
done during the base dispatch view), anything in the view that assumes
these values are present cannot run.  

Most of my views end up with functions which retrieve an object and then do
some basic validation to ensure that a user has permissions, or that the
object is valid in some fashion, or that some set of conditions is met
prior to allowing any method call to happen.  

I have found that without this init method, the vast majority of my views
end up re-writing dispatch which includes the super call.  This is
especially annoying when you have to compare some aspect of the requesting
user with an object that must be looked up with something from args or
kwargs.  My view often already has this machinery built in, but it can't
function without dispatch setting request, args, and kwargs, so to
accomplish my check, I have to duplicate the lookup code in my dispatch
method.

I don't propose mine is the best solution, but I know that it is
non-intrusive, simple, and covers my use cases well.  It is also simple to
accomplish any number of things since `init` merely needs to return a falsy
value to allow the request to pass on through, raise an exception if that
type of failure is desired, or return a response of it wants to hijack the
view entirely.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Russell Keith-Magee  
View profile  
 More options Nov 9 2012, 12:26 am
From: Russell Keith-Magee <russ...@keith-magee.com>
Date: Fri, 9 Nov 2012 13:25:41 +0800
Local: Fri, Nov 9 2012 12:25 am
Subject: Re: Class based views: A standard hook for http-method-independent code

On Fri, Nov 9, 2012 at 1:05 PM, Aaron Merriam <aaronmerr...@gmail.com>wrote:

I'm starting to feel like I'm incredibly dense, because I still don't
understand what your use case *is* - or, at least, why what your proposing
provides any significant advantages over what you can do using basic Python
inheritance techniques.

Specifically, I still can't see why:

class MyView(View):
    def  dispatch(self, request, *args, **kwargs):
        init()
        return super(MyView, self).dispatch(request, *args, **kwargs)

    def init():
        # your init logic here

is superior to the solution provided by using basic Python inheritance:

class MyView(View):
    def  dispatch(self, request, *args, **kwargs):
        # your init logic here
        return super(MyView, self).dispatch(request, *args, **kwargs)

You have exactly the same workflow, and exactly the same order of
operations. You don't need to document any special CBV-specific API --
e.g., when/how init() will be invoked, and with what assumptions about the
request environment can be made -- and you don't have to incur the overhead
of a function call (ok - the overhead is tiny, but let's not pretend it's
zero).

So - can someone explain to me what the advantage is? Why is this init()
method needed?

Yours,
Russ Magee %-)


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jordan Hagan  
View profile  
 More options Nov 9 2012, 12:38 am
From: Jordan Hagan <f...@ephess.co.nz>
Date: Fri, 9 Nov 2012 18:37:37 +1300
Local: Fri, Nov 9 2012 12:37 am
Subject: Re: Class based views: A standard hook for http-method-independent code

Hey Russ,

The main point of concern which I think you may be missing is that
self.kwargs and self.args are set inside dispatch, so using other mixins
that require self.kwargs and self.args to be set (most do) will not work,
without doing:

def dispatch(self, request, *args, **kwargs):
    self.args = args;
    self.kwargs = kwargs
    self.init()
    return super(Class, self).dispatch(request, *args, **kwargs)

Which isn't very tidy, to me having self.args and self.kwargs be set twice
(once in my overridden dispatch method, and once in the original dispatch)
feels wrong. I can't give you a good reason for it, it just feels bad every
time I do it. The only way to work around this is to override dispatch
without calling the original, and essentially duplicate the original
dispatch method with an init call added in.

Cheers,
Jordan

On Fri, Nov 9, 2012 at 6:25 PM, Russell Keith-Magee <russ...@keith-magee.com


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Russell Keith-Magee  
View profile  
 More options Nov 9 2012, 1:05 am
From: Russell Keith-Magee <russ...@keith-magee.com>
Date: Fri, 9 Nov 2012 14:05:01 +0800
Local: Fri, Nov 9 2012 1:05 am
Subject: Re: Class based views: A standard hook for http-method-independent code

Ok… so let's get this straight:

  * init() needs to have access to request, args, kwargs
  * That means your implementation of dispatch() needs to set them.

Sure. I'll pay that. If you assume that an init() method is required, then
sure, you need to set up attributes to support it.

What I don't understand is why the need for an init() method isn't being
challenged in the first place.

Why on earth can't just just take the logic that you're putting in init(),
and put it *in dispatch()*. The sequence of calls is *identical*, and since
*args and **kwargs are locals, they don't need to be set anywhere. What's
the problem with putting the init() logic in the dispatch() method in the
way I described?

Yours,
Russ Magee %-)


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jordan Hagan  
View profile  
 More options Nov 9 2012, 1:34 am
From: Jordan Hagan <f...@ephess.co.nz>
Date: Fri, 9 Nov 2012 19:34:11 +1300
Local: Fri, Nov 9 2012 1:34 am
Subject: Re: Class based views: A standard hook for http-method-independent code

Not quite, other Mixins, take for example
SingleObjectMixin<https://github.com/django/django/blob/master/django/views/generic/det...>
require
access to request, args, kwargs so to utilize the functionality of existing
mixins in init(), we need to set self.request, self.args and self.kwargs in
our dispatch method before dropping down into init(), or do it inside init()

This is the same if we remove the init method entirely, and just try use
the get_object() method on SingleObjectMixin in our overridden dispatch
method.

Since authorization seems to be the main argument so far, I'll use it as an
example - currently we have to do the following:

class MyModel(models.Model):
    name = models.CharField(max_length=100)

    def auth(self, user):
        # do auth

class MyView(SingleObjectMixin, View):
    model = MyModel

    def dispatch(self, request, *args, **kwargs):
        self.request = request
        self.args = args
        self.kwargs = kwargs

        object = self.get_object()
        if object.auth(request.user):
            return super(MyView, self).dispatch(request, *args, **kwargs)
        else:
            # fail somehow

    def get(self, request, *args, **kwargs):
        # behave normally

whereas with some kind of init method, this becomes:

class MyView(SingleObjectMixin, View):
    model = MyModel

    def init(self):
        object = self.get_object()
        if not object.auth(self.request.user):
            # fail somehow

    def get(self, request, *args, **kwargs):
        # behave normally

The example is a bit crude as I just whipped it up, but it gets the point
across I think.

Sorry for dragging this out, I did attempt to explain this earlier however
perhaps I didn't do the best job.

Cheers,
Jordan

On Fri, Nov 9, 2012 at 7:05 PM, Russell Keith-Magee <russ...@keith-magee.com


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Sebastian Goll  
View profile  
 More options Nov 9 2012, 1:44 am
From: Sebastian Goll <sebastian.g...@gmx.de>
Date: Fri, 9 Nov 2012 07:43:33 +0100
Local: Fri, Nov 9 2012 1:43 am
Subject: Re: Class based views: A standard hook for http-method-independent code
On Fri, 9 Nov 2012 14:05:01 +0800

Russell Keith-Magee <russ...@keith-magee.com> wrote:
> Why on earth can't just just take the logic that you're putting in init(),
> and put it *in dispatch()*. The sequence of calls is *identical*, and since
> *args and **kwargs are locals, they don't need to be set anywhere. What's
> the problem with putting the init() logic in the dispatch() method in the
> way I described?

I think the problem is that order of initialization _is_ reversed when
inheritance comes into the game, in the case of handling everything at
the beginning of dispatch(). Consider:

class DepartmentMixin(object):
    def initialize(self, request, *args, **kwargs):
        super(DepartmentMixin, self).initialize(request, *args, **kwargs)
        self.department = get_object_or_404(Department, slug=kwargs['department'])

class ShiftMixin(DepartmentMixin):
    def initialize(self, request, *args, **kwargs):
        super(ShiftMixin, self).initialize(request, *args, **kwargs)
        self.shift = get_object_or_404(Shift, department=self.department, datetime__year=kwargs['year'])

This would not be possible in dispatch() because the super method must
be called at the end of the child method (tail recursion):

class DepartmentMixin(object):
    def dispatch(self, request, *args, **kwargs):
        self.department = get_object_or_404(Department, slug=kwargs['department'])
        return super(DepartmentMixin, self).dispatch(request, *args, **kwargs)

class ShiftMixin(DepartmentMixin):
    def initialize(self, request, *args, **kwargs):
        # THIS DOESN'T WORK: self.department HAS NOT BEEN SET YET.
        self.shift = get_object_or_404(Shift, department=self.department, datetime__year=kwargs['year'])
        return super(ShiftMixin, self).dispatch(request, *args, **kwargs)

I think the control flow is easier to follow in case of initialize()
vs. dispatch(). This doesn't mean that I think initialize() should be
part of core, but the described situation is something I came across in
real life.

Best wishes,
Sebastian.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Daniel Sokolowski  
View profile  
 More options Nov 9 2012, 10:28 am
From: "Daniel Sokolowski" <daniel.sokolow...@klinsight.com>
Date: Fri, 9 Nov 2012 10:28:45 -0500
Local: Fri, Nov 9 2012 10:28 am
Subject: Re: Class based views: A standard hook for http-method-independent code

I’ve done the below in the past, the only issue with that is if you have side effects in parent’s dispatch you don’t want executed but you would also run that risk if you had an initialize() method work flow; in the end I find dispatch() is enough in my experience.

def dispatch(self, request, *args, **kwargs):
    parent_dispatch_return = super(Class, self).dispatch(request, *args, **kwargs)
    ...my code based on values based on the super call...
    return parent_dispatch_return

From: Jordan Hagan
Sent: Friday, November 09, 2012 12:37 AM
To: django-developers@googlegroups.com
Subject: Re: Class based views: A standard hook for http-method-independent code

Hey Russ,

The main point of concern which I think you may be missing is that self.kwargs and self.args are set inside dispatch, so using other mixins that require self.kwargs and self.args to be set (most do) will not work, without doing:

def dispatch(self, request, *args, **kwargs):
    self.args = args;
    self.kwargs = kwargs
    self.init()
    return super(Class, self).dispatch(request, *args, **kwargs)

Which isn't very tidy, to me having self.args and self.kwargs be set twice (once in my overridden dispatch method, and once in the original dispatch) feels wrong. I can't give you a good reason for it, it just feels bad every time I do it. The only way to work around this is to override dispatch without calling the original, and essentially duplicate the original dispatch method with an init call added in.

Cheers,
Jordan

On Fri, Nov 9, 2012 at 6:25 PM, Russell Keith-Magee <russ...@keith-magee.com> wrote:

  On Fri, Nov 9, 2012 at 1:05 PM, Aaron Merriam <aaronmerr...@gmail.com> wrote:

    Without setting request, args, and kwargs on on the view instance (which is done during the base dispatch view), anything in the view that assumes these values are present cannot run.  

    Most of my views end up with functions which retrieve an object and then do some basic validation to ensure that a user has permissions, or that the object is valid in some fashion, or that some set of conditions is met prior to allowing any method call to happen.  

    I have found that without this init method, the vast majority of my views end up re-writing dispatch which includes the super call.  This is especially annoying when you have to compare some aspect of the requesting user with an object that must be looked up with something from args or kwargs.  My view often already has this machinery built in, but it can't function without dispatch setting request, args, and kwargs, so to accomplish my check, I have to duplicate the lookup code in my dispatch method.

    I don't propose mine is the best solution, but I know that it is non-intrusive, simple, and covers my use cases well.  It is also simple to accomplish any number of things since `init` merely needs to return a falsy value to allow the request to pass on through, raise an exception if that type of failure is desired, or return a response of it wants to hijack the view entirely.

  I'm starting to feel like I'm incredibly dense, because I still don't understand what your use case *is* - or, at least, why what your proposing provides any significant advantages over what you can do using basic Python inheritance techniques.

  Specifically, I still can't see why:

  class MyView(View):
      def  dispatch(self, request, *args, **kwargs):
          init()
          return super(MyView, self).dispatch(request, *args, **kwargs)

      def init():
          # your init logic here

  is superior to the solution provided by using basic Python inheritance:

  class MyView(View):
      def  dispatch(self, request, *args, **kwargs):
          # your init logic here
          return super(MyView, self).dispatch(request, *args, **kwargs)

  You have exactly the same workflow, and exactly the same order of operations. You don't need to document any special CBV-specific API -- e.g., when/how init() will be invoked, and with what assumptions about the request environment can be made -- and you don't have to incur the overhead of a function call (ok - the overhead is tiny, but let's not pretend it's zero).

  So - can someone explain to me what the advantage is? Why is this init() method needed?

  Yours,
  Russ Magee %-)

  --
  You received this message because you are subscribed to the Google Groups "Django developers" group.

  To post to this group, send email to django-developers@googlegroups.com.
  To unsubscribe from this group, send email to mailto:django-developers%2Bunsubscribe@googlegroups.com.
  For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.

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

Daniel Sokolowski
http://webdesign.danols.com/


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Aaron Merriam  
View profile  
 More options Nov 9 2012, 3:12 pm
From: Aaron Merriam <aaronmerr...@gmail.com>
Date: Fri, 9 Nov 2012 12:12:36 -0800 (PST)
Local: Fri, Nov 9 2012 3:12 pm
Subject: Re: Class based views: A standard hook for http-method-independent code

That pattern has nasty side-effects.  It can be used in some cases but it
fails in most.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Diederik van der Boor  
View profile  
 More options Nov 12 2012, 8:38 am
From: Diederik van der Boor <vdb...@gmail.com>
Date: Mon, 12 Nov 2012 14:38:29 +0100
Local: Mon, Nov 12 2012 8:38 am
Subject: Re: Class based views: A standard hook for http-method-independent code

Op 9 nov. 2012, om 07:05 heeft Russell Keith-Magee het volgende geschreven:

> What I don't understand is why the need for an init() method isn't being challenged in the first place.

> Why on earth can't just just take the logic that you're putting in init(), and put it *in dispatch()*. The sequence of calls is *identical*, and since *args and **kwargs are locals, they don't need to be set anywhere. What's the problem with putting the init() logic in the dispatch() method in the way I described?

It has to do with the order of execution, the derived class always runs first.
When a permission check is in dispatch(), anything that overrides dispatch() runs before the permission check.
The same also applies to any other initialization code, a derived class can never build on top of that because it should call

Please allow me to paraphrase my previous explanation (https://groups.google.com/d/msg/django-developers/7c7aI-slGNc/a-DYFrI...)

What is the problem with overriding dispatch()?
When overriding dispatch(), get() or post() the flow is always:

def dispatch(self, request, *args, **kwargs):
    # my code here.
    return super(…).dispatch(request, *args, **kwargs)

The same also applies to get() and post().
In other words, the last deriving class on top of the inheritance chain is always initializing first before it's base classes.
It can't rely on a base class to do some initialization.

With our permission check in the base class' dispatch() method, anything deriving from that effectively
couldn't override dispatch() anymore because that would run before the permission check.

How does the init method fix this?
By doing a self.init() in the top-most dispatch() method, each class in the inheritance chain has a chance to fetch the objects it needs to have.

That code can be written as:

def init(self):
    super(..).init()
    # my code here.

Now, the base class can initialize, then the deriving class.
With a larger inheritance chain, this behavior becomes crucial.
Each class can build upon what the other has prepared already.

Greetings,

Diederik


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Daniel Sokolowski  
View profile  
 More options Nov 14 2012, 8:49 am
From: "Daniel Sokolowski" <daniel.sokolow...@klinsight.com>
Date: Wed, 14 Nov 2012 08:48:54 -0500
Local: Wed, Nov 14 2012 8:48 am
Subject: Re: Class based views: A standard hook for http-method-independent code

Can you elaborate the nasty side effects you are thinking of? I can’t think of any that that the base views do to warrant your statement.

From: Aaron Merriam
Sent: Friday, November 09, 2012 3:12 PM
To: django-developers@googlegroups.com
Subject: Re: Class based views: A standard hook for http-method-independent code

That pattern has nasty side-effects.  It can be used in some cases but it fails in most.

On Friday, November 9, 2012 8:28:47 AM UTC-7, Daniel Sokolowski wrote:

  I’ve done the below in the past, the only issue with that is if you have side effects in parent’s dispatch you don’t want executed but you would also run that risk if you had an initialize() method work flow; in the end I find dispatch() is enough in my experience.

  def dispatch(self, request, *args, **kwargs):
      parent_dispatch_return = super(Class, self).dispatch(request, *args, **kwargs)
      ...my code based on values based on the super call...
      return parent_dispatch_return

  From: Jordan Hagan
  Sent: Friday, November 09, 2012 12:37 AM
  To: django-d...@googlegroups.com
  Subject: Re: Class based views: A standard hook for http-method-independent code

  Hey Russ,

  The main point of concern which I think you may be missing is that self.kwargs and self.args are set inside dispatch, so using other mixins that require self.kwargs and self.args to be set (most do) will not work, without doing:

  def dispatch(self, request, *args, **kwargs):
      self.args = args;
      self.kwargs = kwargs
      self.init()
      return super(Class, self).dispatch(request, *args, **kwargs)

  Which isn't very tidy, to me having self.args and self.kwargs be set twice (once in my overridden dispatch method, and once in the original dispatch) feels wrong. I can't give you a good reason for it, it just feels bad every time I do it. The only way to work around this is to override dispatch without calling the original, and essentially duplicate the original dispatch method with an init call added in.

  Cheers,
  Jordan

  On Fri, Nov 9, 2012 at 6:25 PM, Russell Keith-Magee <rus...@keith-magee.com> wrote:

    On Fri, Nov 9, 2012 at 1:05 PM, Aaron Merriam <aaronm...@gmail.com> wrote:

      Without setting request, args, and kwargs on on the view instance (which is done during the base dispatch view), anything in the view that assumes these values are present cannot run.  

      Most of my views end up with functions which retrieve an object and then do some basic validation to ensure that a user has permissions, or that the object is valid in some fashion, or that some set of conditions is met prior to allowing any method call to happen.  

      I have found that without this init method, the vast majority of my views end up re-writing dispatch which includes the super call.  This is especially annoying when you have to compare some aspect of the requesting user with an object that must be looked up with something from args or kwargs.  My view often already has this machinery built in, but it can't function without dispatch setting request, args, and kwargs, so to accomplish my check, I have to duplicate the lookup code in my dispatch method.

      I don't propose mine is the best solution, but I know that it is non-intrusive, simple, and covers my use cases well.  It is also simple to accomplish any number of things since `init` merely needs to return a falsy value to allow the request to pass on through, raise an exception if that type of failure is desired, or return a response of it wants to hijack the view entirely.

    I'm starting to feel like I'm incredibly dense, because I still don't understand what your use case *is* - or, at least, why what your proposing provides any significant advantages over what you can do using basic Python inheritance techniques.

    Specifically, I still can't see why:

    class MyView(View):
        def  dispatch(self, request, *args, **kwargs):
            init()
            return super(MyView, self).dispatch(request, *args, **kwargs)

        def init():
            # your init logic here

    is superior to the solution provided by using basic Python inheritance:

    class MyView(View):
        def  dispatch(self, request, *args, **kwargs):
            # your init logic here
            return super(MyView, self).dispatch(request, *args, **kwargs)

    You have exactly the same workflow, and exactly the same order of operations. You don't need to document any special CBV-specific API -- e.g., when/how init() will be invoked, and with what assumptions about the request environment can be made -- and you don't have to incur the overhead of a function call (ok - the overhead is tiny, but let's not pretend it's zero).

    So - can someone explain to me what the advantage is? Why is this init() method needed?

    Yours,
    Russ Magee %-)

    --
    You received this message because you are subscribed to the Google Groups "Django developers" group.

    To post to this group, send email to django-d...@googlegroups.com.
    To unsubscribe from this group, send email to mailto:django-developers%2Bunsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.

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

  Daniel Sokolowski
  http://webdesign.danols.com/

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

Daniel Sokolowski
http://webdesign.danols.com/


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Alex Ogier  
View profile  
 More options Nov 14 2012, 10:36 am
From: Alex Ogier <alex.og...@gmail.com>
Date: Wed, 14 Nov 2012 10:35:52 -0500
Local: Wed, Nov 14 2012 10:35 am
Subject: Re: Class based views: A standard hook for http-method-independent code

For example, you miss Http404 and other error responses, which are
implemented as exceptional control flow. In addition, you can't do any
preprocessing of the request; for example, you can't set up any invariants
before your actual view method is called.

Best,
Alex Ogier

On Wed, Nov 14, 2012 at 8:48 AM, Daniel Sokolowski <


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Daniel Sokolowski  
View profile  
 More options Nov 14 2012, 10:58 am
From: "Daniel Sokolowski" <daniel.sokolow...@klinsight.com>
Date: Wed, 14 Nov 2012 10:58:43 -0500
Local: Wed, Nov 14 2012 10:58 am
Subject: Re: Class based views: A standard hook for http-method-independent code

Hmm, ok, so that is only and issue if you don’t know the side effects calling super when dealing with non django provided views - and you can still pre-process request before calling super.  

So at the moment I can understand the appeal of init() as shown in the example but fail to see where I couldn’t just use dispatch() instead. In the past when we needed to tie permission checks I opted into making a view mixin to override dispatch similar to this one: https://github.com/lukaszb/django-guardian/blob/master/guardian/mixin...

Perhaps people that do find this init() method worthwhile should voice so. Thanks
From: Alex Ogier
Sent: Wednesday, November 14, 2012 10:35 AM
To: django-developers@googlegroups.com
Subject: Re: Class based views: A standard hook for http-method-independent code

For example, you miss Http404 and other error responses, which are implemented as exceptional control flow. In addition, you can't do any preprocessing of the request; for example, you can't set up any invariants before your actual view method is called.

Best,
Alex Ogier

On Wed, Nov 14, 2012 at 8:48 AM, Daniel Sokolowski <daniel.sokolow...@klinsight.com> wrote:

  Can you elaborate the nasty side effects you are thinking of? I can’t think of any that that the base views do to warrant your statement.

  From: Aaron Merriam
  Sent: Friday, November 09, 2012 3:12 PM
  To: django-developers@googlegroups.com
  Subject: Re: Class based views: A standard hook for http-method-independent code

  That pattern has nasty side-effects.  It can be used in some cases but it fails in most.

  On Friday, November 9, 2012 8:28:47 AM UTC-7, Daniel Sokolowski wrote:
    I’ve done the below in the past, the only issue with that is if you have side effects in parent’s dispatch you don’t want executed but you would also run that risk if you had an initialize() method work flow; in the end I find dispatch() is enough in my experience.

    def dispatch(self, request, *args, **kwargs):
        parent_dispatch_return = super(Class, self).dispatch(request, *args, **kwargs)
        ...my code based on values based on the super call...
        return parent_dispatch_return
--
You received this message because you are subscribed to the Google Groups "Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to django-developers+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.

Daniel Sokolowski
http://webdesign.danols.com/


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Aaron Merriam  
View profile  
 More options Nov 14 2012, 11:18 pm
From: Aaron Merriam <aaronmerr...@gmail.com>
Date: Wed, 14 Nov 2012 20:18:34 -0800 (PST)
Local: Wed, Nov 14 2012 11:18 pm
Subject: Re: Class based views: A standard hook for http-method-independent code

If the super call changes any data then by the time you've run whatever
code comes after the super call, the changes have already occured.  

   - If you wait to call super before running your own code, then request,
   args, and kwargs are not available on the request, so anything that depends
   on them being there (such as self.get_object()) will not work, so it must
   be re-implemented,
   - Otherwise you have to set request, args, kwargs yourself which does
   not feel very DRY.

For me, the entire reason I would like this change, is so that I can do
something before dispatch that uses self.request/args/kwargs.  Everything I
want can be accomplished within dispatch, but not as cleanly, or as DRY as
if this method hook existed.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Daniel Sokolowski  
View profile  
 More options Nov 16 2012, 9:09 am
From: "Daniel Sokolowski" <daniel.sokolow...@klinsight.com>
Date: Fri, 16 Nov 2012 09:09:20 -0500
Local: Fri, Nov 16 2012 9:09 am
Subject: Re: Class based views: A standard hook for http-method-independent code

I like this approach.

From: George Hickman
Sent: Thursday, November 15, 2012 7:27 AM
To: django-developers@googlegroups.com
Subject: Re: Class based views: A standard hook for http-method-independent code

I have a slightly different proposal, one where we can avoid the extra hook but hopefully cover everyone's use cases too.

https://github.com/ghickman/django/commit/85ac39a481074c25af1ed72a7a1...

I've personally never liked the setting of args, kwargs & request from within dispatch since it seems like it's feature creep of the dispatch method. However I'm also in the same boat as many of the other posters here in needing to do permissions related checks before dispatch is called.

With my suggestion above you would be able to put your pre-dispatch code in a subclasses overridden dispatch before calling super while also depending on args, kwargs & request on self.

On Thursday, November 15, 2012 4:18:34 AM UTC, Aaron Merriam wrote:

  If the super call changes any data then by the time you've run whatever code comes after the super call, the changes have already occured.  

    a.. If you wait to call super before running your own code, then request, args, and kwargs are not available on the request, so anything that depends on them being there (such as self.get_object()) will not work, so it must be re-implemented,  
    b.. Otherwise you have to set request, args, kwargs yourself which does not feel very DRY.

  For me, the entire reason I would like this change, is so that I can do something before dispatch that uses self.request/args/kwargs.  Everything I want can be accomplished within dispatch, but not as cleanly, or as DRY as if this method hook existed.

  On Wednesday, November 14, 2012 6:49:06 AM UTC-7, Daniel Sokolowski wrote:
    Can you elaborate the nasty side effects you are thinking of? I can’t think of any that that the base views do to warrant your statement.

    From: Aaron Merriam
    Sent: Friday, November 09, 2012 3:12 PM
    To: django-d...@googlegroups.com
    Subject: Re: Class based views: A standard hook for http-method-independent code

    That pattern has nasty side-effects.  It can be used in some cases but it fails in most.

    On Friday, November 9, 2012 8:28:47 AM UTC-7, Daniel Sokolowski wrote:
      I’ve done the below in the past, the only issue with that is if you have side effects in parent’s dispatch you don’t want executed but you would also run that risk if you had an initialize() method work flow; in the end I find dispatch() is enough in my experience.

      def dispatch(self, request, *args, **kwargs):
          parent_dispatch_return = super(Class, self).dispatch(request, *args, **kwargs)
          ...my code based on values based on the super call...
          return parent_dispatch_return

      From: Jordan Hagan
      Sent: Friday, November 09, 2012 12:37 AM
      To: django-d...@googlegroups.com
      Subject: Re: Class based views: A standard hook for http-method-independent code

      Hey Russ,

      The main point of concern which I think you may be missing is that self.kwargs and self.args are set inside dispatch, so using other mixins that require self.kwargs and self.args to be set (most do) will not work, without doing:

      def dispatch(self, request, *args, **kwargs):
          self.args = args;
          self.kwargs = kwargs
          self.init()
          return super(Class, self).dispatch(request, *args, **kwargs)

      Which isn't very tidy, to me having self.args and self.kwargs be set twice (once in my overridden dispatch method, and once in the original dispatch) feels wrong. I can't give you a good reason for it, it just feels bad every time I do it. The only way to work around this is to override dispatch without calling the original, and essentially duplicate the original dispatch method with an init call added in.

      Cheers,
      Jordan

      On Fri, Nov 9, 2012 at 6:25 PM, Russell Keith-Magee <rus...@keith-magee.com> wrote:

        On Fri, Nov 9, 2012 at 1:05 PM, Aaron Merriam <aaronm...@gmail.com> wrote:

          Without setting request, args, and kwargs on on the view instance (which is done during the base dispatch view), anything in the view that assumes these values are present cannot run.  

          Most of my views end up with functions which retrieve an object and then do some basic validation to ensure that a user has permissions, or that the object is valid in some fashion, or that some set of conditions is met prior to allowing any method call to happen.  

          I have found that without this init method, the vast majority of my views end up re-writing dispatch which includes the super call.  This is especially annoying when you have to compare some aspect of the requesting user with an object that must be looked up with something from args or kwargs.  My view often already has this machinery built in, but it can't function without dispatch setting request, args, and kwargs, so to accomplish my check, I have to duplicate the lookup code in my dispatch method.

          I don't propose mine is the best solution, but I know that it is non-intrusive, simple, and covers my use cases well.  It is also simple to accomplish any number of things since `init` merely needs to return a falsy value to allow the request to pass on through, raise an exception if that type of failure is desired, or return a response of it wants to hijack the view entirely.

        I'm starting to feel like I'm incredibly dense, because I still don't understand what your use case *is* - or, at least, why what your proposing provides any significant advantages over what you can do using basic Python inheritance techniques.

        Specifically, I still can't see why:

        class MyView(View):
            def  dispatch(self, request, *args, **kwargs):
                init()
                return super(MyView, self).dispatch(request, *args, **kwargs)

            def init():
                # your init logic here

        is superior to the solution provided by using basic Python inheritance:

        class MyView(View):
            def  dispatch(self, request, *args, **kwargs):
                # your init logic here
                return super(MyView, self).dispatch(request, *args, **kwargs)

        You have exactly the same workflow, and exactly the same order of operations. You don't need to document any special CBV-specific API -- e.g., when/how init() will be invoked, and with what assumptions about the request environment can be made -- and you don't have to incur the overhead of a function call (ok - the overhead is tiny, but let's not pretend it's zero).

        So - can someone explain to me what the advantage is? Why is this init() method needed?

        Yours,
        Russ Magee %-)

        --
        You received this message because you are subscribed to the Google Groups "Django developers" group.

        To post to this group, send email to django-d...@googlegroups.com.
        To unsubscribe from this group, send email to mailto:django-developers%2Bunsubscribe@googlegroups.com.
        For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.

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

      Daniel Sokolowski
      http://webdesign.danols.com/

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

    Daniel Sokolowski
    http://webdesign.danols.com/

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

Daniel Sokolowski
http://webdesign.danols.com/


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Aaron Merriam  
View profile  
 More options Nov 17 2012, 12:02 am
From: Aaron Merriam <aaronmerr...@gmail.com>
Date: Fri, 16 Nov 2012 21:02:14 -0800 (PST)
Local: Sat, Nov 17 2012 12:02 am
Subject: Re: Class based views: A standard hook for http-method-independent code

This is great.  +1.  Better than an additional hook.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jeremy Dunck  
View profile  
 More options Nov 16 2012, 1:52 pm
From: Jeremy Dunck <jdu...@gmail.com>
Date: Fri, 16 Nov 2012 10:52:44 -0800
Local: Fri, Nov 16 2012 1:52 pm
Subject: Re: Class based views: A standard hook for http-method-independent code
+1, this looks like a good change anyway and doesn't smell to me.

On Fri, Nov 16, 2012 at 6:09 AM, Daniel Sokolowski


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jordan Hagan  
View profile  
 More options Nov 18 2012, 4:52 pm
From: Jordan Hagan <f...@ephess.co.nz>
Date: Mon, 19 Nov 2012 10:51:53 +1300
Local: Sun, Nov 18 2012 4:51 pm
Subject: Re: Class based views: A standard hook for http-method-independent code

+1, this looks like a better solution than the hook method.

...

read more »


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Mike Fogel  
View profile  
 More options Nov 21 2012, 1:30 am
From: Mike Fogel <m...@fogel.ca>
Date: Tue, 20 Nov 2012 22:30:37 -0800 (PST)
Local: Wed, Nov 21 2012 1:30 am
Subject: Re: Class based views: A standard hook for http-method-independent code

+1, this allows me what I want - to have http method-independent code that
uses self.args, self.kwargs and self.request.

...

read more »


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Michael Bylstra  
View profile  
 More options Feb 11, 12:05 pm
From: Michael Bylstra <mbyls...@gmail.com>
Date: Mon, 11 Feb 2013 09:05:18 -0800 (PST)
Local: Mon, Feb 11 2013 12:05 pm
Subject: Re: Class based views: A standard hook for http-method-independent code

The git link seems to be broken. I'd love to see this bit of code everyone
is raving about!


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
George Hickman  
View profile  
 More options Feb 11, 12:16 pm
From: George Hickman <geo...@ghickman.co.uk>
Date: Mon, 11 Feb 2013 17:16:14 +0000
Local: Mon, Feb 11 2013 12:16 pm
Subject: Re: Class based views: A standard hook for http-method-independent code

Michael,

There's not to much to it I'm afraid!
https://github.com/ghickman/django/commit/ca2e6d68764c0f2215e43196b6e...

George

...

read more »


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages < Older 
« Back to Discussions « Newer topic     Older topic »