As it seems that there is no longer any real opposition to this ticket (if 
there is, now would be the time to speak up) I'll go ahead and prepare a 
patch against the current trunk and get it uploaded to trac and see where 
we get to from there.

Hopefully I'll get a chance to take a look at this this week, I'll post a 
link to the trac ticket here once I've opened it.

Cheers,
Jordan

On Friday, 2 November 2012 04:00:07 UTC+13, Andre Terra wrote:
>
> At first I wasn't sure about this hook, but after working with permissions 
> in CBVs I can see how this would allow for much simpler code, especially 
> when you're implementing a lot of subclassing. I tend to get carried away 
> in writing mixins and base classes for my views, so yeah, I'm +1 on this 
> too.
>  
> Cheers,
> AT
>
> -- Sent from my phone, please excuse any typos. --
> On Nov 1, 2012 12:31 PM, "Aaron Merriam" <aaronm...@gmail.com<javascript:>> 
> wrote:
>
>> Just wanted to put my +1 into this thread.  I've been fighting for a 
>> clean way to implement permissions in class based views and the 'init' 
>> method would help my implementation be a lot more DRY.
>>
>> On Wednesday, October 31, 2012 12:42:33 PM UTC-6, Jordan Hagan wrote:
>>>
>>> Diedreik,
>>>
>>> Thanks for your comments - your solution seems similar to the one 
>>> proposed by Meshy unless I'm missing something (https://gist.github.com/
>>> **1957251 <https://gist.github.com/1957251>). It is good to see 
>>> multiple people coming up with the same solution to the issue independently 
>>> though as that to me is an indication that we're moving in the right 
>>> direction.
>>>
>>> Meshy,
>>>
>>> Thanks for the link - the django-braces project looks useful - I'll 
>>> probably start using that.
>>>
>>> I would love to get some input from a core developer (or two) on this to 
>>> see where they stand. From where I'm sitting there seems to be a number of 
>>> people working around this problem in more or less the same manner, and 
>>> most of the arguments against haven't taken into 
>>> consideration compatibility **with other mixins, already existing class 
>>> methods, etc.
>>>
>>> I would be happy to put together a patch in a ticket on trac and do any 
>>> other grunt work required to make this happen.
>>>
>>> Cheers,
>>> Jordan
>>>
>>> On Wednesday, 31 October 2012 22:57:28 UTC+13, Meshy wrote:
>>>>
>>>> Marc and I have been using a mixin to override `dispatch()` with this 
>>>> functionality. He has an ongoing pull request on 
>>>> django-braces<https://github.com/brack3t/django-braces/pull/8>with the 
>>>> code. I hope this can be useful to some of you.
>>>>
>>>> Meshy.
>>>>
>>>> On Wednesday, October 31, 2012 9:49:26 AM UTC, Diederik van der Boor 
>>>> wrote:
>>>>>
>>>>> Hi,
>>>>>
>>>>> Please allow me to add my €0.02.
>>>>> In a large project I've experienced a similar issue; and we solved it 
>>>>> in a slightly different way.
>>>>> What we also noticed was:
>>>>> - overriding dispatch(), get() or post() wasn't good enough anymore.
>>>>> - the views need some initialization moment before their workflow (in 
>>>>> get/post of the base classes) start.
>>>>>
>>>>> What we ended up with is this base class (simplified a bit):
>>>>> https://gist.github.com/**3985939 <https://gist.github.com/3985939>
>>>>>
>>>>> *I seriously propose having such init() function in the Django views.*
>>>>> Mind you, that took a heated debate in the organization I was 
>>>>> contacted for, so please allow me to explain to context here.
>>>>> I think we've found a missing cornerstone in the way the class based 
>>>>> views are structured, and there is an easy fix.
>>>>>
>>>>> *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.
>>>>>
>>>>>
>>>>> All of a sudden, we could do things like this:
>>>>>
>>>>> 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()
>>>>>         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
>>>>>
>>>>> This is a list view for photo's, and it's limited to a current photo 
>>>>> album.
>>>>> The alternative is making a DetailView, and putting the photo's 
>>>>> somewhere in get_context_data() and thereby loose what the list view 
>>>>> has to offer.
>>>>> Now we can just state it's a list view (which it is), and introduce 
>>>>> the filter easily.
>>>>>
>>>>> Without the init() method, you're probably knotting that somewhere in 
>>>>> the get_queryset() and get_context_data(),
>>>>> without having a clear path of that's happening. Thanks to the simple 
>>>>> init() method is all remains clean.
>>>>>
>>>>>
>>>>> *Some background of our use-case*
>>>>> The project is made for health care and privacy must be fully 
>>>>> guaranteed.
>>>>> Hence, all views have to implement a permission check, which we wanted 
>>>>> to have in the base class.
>>>>> The only place to hook things up, was before the super call to 
>>>>>  dispatch(), otherwise the view already executed.
>>>>>
>>>>> At the same time, the permission check needs information from things 
>>>>> like "self.object", and the URL kwargs.
>>>>> That's because the permission check is role based; clients only see 
>>>>> their views, counselors may inspect their clients, etc..
>>>>> Implementing the check half-way in the regular get() and post() 
>>>>> workflow wasn't an option as it's easy to miss.
>>>>>
>>>>> With the init() method, we allow the view to initialize, and fetch all 
>>>>> objects, so more sophisticated code can be performed afterwards.
>>>>> Currently the permission check still fetches the objects itself as 
>>>>> well, which will likely change in the future when the checks have more 
>>>>> role-based options.
>>>>>
>>>>>
>>>>> I hope this gives a clear explanation why such method would be 
>>>>> beneficial to Django's class based views.
>>>>>
>>>>> Looking forward to your suggestions and response,
>>>>>
>>>>> Diederik
>>>>>
>>>>>
>>>>>  -- 
>>>>> linkedin: 
>>>>> http://nl.linkedin.**com/in/vdboor<http://nl.linkedin.com/in/vdboor>
>>>>> website: http://www.edoburu.**nl/ <http://www.edoburu.nl/>
>>>>>  
>>>>>
>>>>> Op 30 okt. 2012, om 22:44 heeft Jordan Hagan het volgende geschreven:
>>>>>
>>>>> I would really like to see something like Meshy's proposed solution 
>>>>> implemented as this is an issue that I've run into a few times as well.
>>>>>
>>>>> Although I can appreciate TiNo's argument of:
>>>>>
>>>>> > self.request = request
>>>>> > ...
>>>>>
>>>>> This creates a problem for methods that are going to be used in the 
>>>>> overridden dispatch method and the dispatched method that need access to 
>>>>> these attributes as they will need to be passed in as a parameter:
>>>>>
>>>>> in dispatch:
>>>>> self.some_method(request, *args, **kwargs)
>>>>>
>>>>> in dispatched:
>>>>> self.some_method(self.request, *self.args, **self.kwargs)
>>>>>
>>>>> which is just really messy.
>>>>>
>>>>> In addition to this methods from other generic view mixins cannot be 
>>>>> used in the overridden dispatch method as they expect these class 
>>>>> attributes to be available - 'get_object' on SingleObjectMixin is a good 
>>>>> example of this as it requires self.kwargs to function:
>>>>>
>>>>> https://github.com/django/**django/blob/master/django/**
>>>>> views/generic/detail.py#L34<https://github.com/django/django/blob/master/django/views/generic/detail.py#L34>
>>>>>
>>>>> The only options available to us are monkey patching or code 
>>>>> duplication, neither of which offer a good solution to this problem. 
>>>>> Generic views are great for reducing boilerplate in code, and adding a 
>>>>> hook 
>>>>> in this case would do just that. Without this hook I'm forced to add code 
>>>>> like the following to each of my projects as a workaround 
>>>>> https://gist.**github.com/3983252 <https://gist.github.com/3983252>
>>>>>
>>>>> Cheers,
>>>>> Jordan
>>>>>
>>>>> On Saturday, 17 March 2012 09:52:43 UTC+13, Mike Fogel wrote:
>>>>>
>>>>>> > I don't really see what difference another function makes. 
>>>>>> Sayhttps://gist.github.com/**1957251is<http://gist.github.com/1957251is>implemented,
>>>>>>  what makes: 
>>>>>> > 
>>>>>> > def prepare_view(self, request, *args, **kwargs): 
>>>>>> >     # the thing I want to do 
>>>>>> >     super(ClassName, self).prepare_view(request, *args, **kwargs) 
>>>>>> > 
>>>>>> > preferable over: 
>>>>>> > 
>>>>>> > def dispatch(self, request, *args, **kwargs): 
>>>>>> >     # the thing I want to do 
>>>>>> >     super(ClassName, self).dispatch(request, *args, **kwargs) 
>>>>>> > 
>>>>>> > ? 
>>>>>>
>>>>>> https://gist.github.com/**1957251 <https://gist.github.com/1957251>would 
>>>>>> allow: 
>>>>>>
>>>>>> def prepare_view(self, request, *args, **kwargs): 
>>>>>>     super(ClassName, self).prepare_view(request, *args, **kwargs) 
>>>>>>     # the thing I want to do - can use self.request, self.args, 
>>>>>> self.kwargs 
>>>>>>
>>>>>> As things stand now, I don't know of a graceful manner to use 
>>>>>> self.request in a http-method independent way. 
>>>>>>
>>>>>> FWIW, I've ran into this restriction a number of times, including 
>>>>>> today. If one of the core devs will nod approval on this, I'll open a 
>>>>>> ticket and attach this gist to it. 
>>>>>>
>>>>>> Cheers, 
>>>>>>
>>>>>> Mike 
>>>>>>
>>>>>> On Mar 4, 9:45 am, Tino de Bruijn <tin...@gmail.com> wrote: 
>>>>>> > I don't really see what difference another function makes. 
>>>>>> Sayhttps://gist.github.com/**1957251is<http://gist.github.com/1957251is>implemented,
>>>>>>  what makes: 
>>>>>> > 
>>>>>> > def prepare_view(self, request, *args, **kwargs): 
>>>>>> >     # the thing I want to do 
>>>>>> >     super(ClassName, self).prepare_view(request, *args, **kwargs) 
>>>>>> > 
>>>>>> > preferable over: 
>>>>>> > 
>>>>>> > def dispatch(self, request, *args, **kwargs): 
>>>>>> >     # the thing I want to do 
>>>>>> >     super(ClassName, self).dispatch(request, *args, **kwargs) 
>>>>>> > 
>>>>>> > ? 
>>>>>> > 
>>>>>> > You'll still have a super call because otherwise you have to repeat 
>>>>>> the 
>>>>>> > 
>>>>>> > self.request = request 
>>>>>> > self.args = args 
>>>>>> > self.kwargs = kwargs 
>>>>>> > 
>>>>>> > part of prepare_view. 
>>>>>> > 
>>>>>> > What is wrong with overriding dispatch and calling super? (Or not, 
>>>>>> if you 
>>>>>> > don't want to progress in the view) 
>>>>>> > 
>>>>>> > Tino 
>>>>>>
>>>>>> -- 
>>>>> 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/-/**uYmm9IR6P7QJ<https://groups.google.com/d/msg/django-developers/-/uYmm9IR6P7QJ>
>>>>> .
>>>>> 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<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 view this discussion on the web visit 
>> https://groups.google.com/d/msg/django-developers/-/Um5fZBppDqMJ.
>> To post to this group, send email to 
>> django-d...@googlegroups.com<javascript:>
>> .
>> To unsubscribe from this group, send email to 
>> django-develop...@googlegroups.com <javascript:>.
>> 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 view this discussion on the web visit 
https://groups.google.com/d/msg/django-developers/-/f-26zaSeKHgJ.
To post to this group, send email to django-developers@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