Django

Code

Ticket #6735 (assigned)

Opened 2 years ago

Last modified 1 month ago

Class-based generic views

Reported by: jkocherhans Assigned to: telenieko (accepted)
Milestone: Component: Generic views
Version: Keywords:
Cc: floguy@gmail.com, david, benjixx, carljm, jezdez, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com, mjmalone@gmail.com, taavi@taijala.com, narma.nsk@gmail.com, obeattie, darkpixel, Ciantic, brian@unbracketed.com Triage Stage: Accepted
Has patch: 1 Needs documentation: 1
Needs tests: 0 Patch needs improvement: 0

Description (Last modified by jkocherhans)

Rewrite generic views to be class based, but leave the existing generic views as-is for now.

Attachments

new-generic-views.diff (11.8 kB) - added by jkocherhans on 03/07/08 10:49:00.
new-generic-views.2.diff (26.9 kB) - added by jkocherhans on 03/15/08 15:21:18.
new-generic-views.3.diff (12.4 kB) - added by jkocherhans on 03/15/08 15:22:26.
generic-views.diff (21.6 kB) - added by jkocherhans on 03/20/08 14:04:39.
Now list_detail views can play too.
generic-views.2.diff (21.3 kB) - added by jkocherhans on 03/20/08 14:17:34.
DjangoGenericViews.png (89.9 kB) - added by telenieko on 07/08/08 11:55:03.
class hierarchy

Change History

03/07/08 10:49:00 changed by jkocherhans

  • attachment new-generic-views.diff added.

03/07/08 10:50:21 changed by jkocherhans

  • needs_better_patch changed.
  • needs_tests changed.
  • needs_docs changed.

This ticket refs #3639 use newforms in generic create_update view

03/07/08 10:52:03 changed by jkocherhans

  • needs_docs set to 1.
  • needs_tests set to 1.

The tests need to be fleshed out a little more, and we need a plan for backwards compatibility, but the classes themselves are fairly close, I think.

03/08/08 01:08:08 changed by floguy

  • cc set to floguy@gmail.com.

03/10/08 10:18:59 changed by brosner

03/11/08 15:19:05 changed by jacob

  • stage changed from Unreviewed to Design decision needed.

03/15/08 15:21:18 changed by jkocherhans

  • attachment new-generic-views.2.diff added.

03/15/08 15:22:26 changed by jkocherhans

  • attachment new-generic-views.3.diff added.

03/15/08 15:23:42 changed by jkocherhans

post_save is now on_success and I've added hook to return the rendered template.

03/18/08 23:04:02 changed by jkocherhans

  • needs_tests deleted.
  • stage changed from Design decision needed to Accepted.

Sorry about the mess of patch files. I forgot to check the "replace me" box. Anyhow, Adrian and Jacob are both in favor after a discussion today, so I'm changing status to Accepted.

03/20/08 14:04:39 changed by jkocherhans

  • attachment generic-views.diff added.

Now list_detail views can play too.

03/20/08 14:05:37 changed by jkocherhans

  • description changed.
  • summary changed from Class-based generic create/update/delete views to Class-based generic views.

03/20/08 14:06:06 changed by jkocherhans

  • description changed.

03/20/08 14:17:34 changed by jkocherhans

  • attachment generic-views.2.diff added.

03/25/08 11:17:05 changed by daveyjoe

The EditView? class is passing back a exception when I use it with a model that has a field with editable set to False (editable=False). I'm only starting out with python so please ignore this if the problem is at my end.

Traceback is here... http://dpaste.com/41195/

05/19/08 11:28:30 changed by david

  • cc changed from floguy@gmail.com to floguy@gmail.com, larlet@gmail.com.

05/23/08 10:10:29 changed by bailey@akamai.com

This is great. it looks like one of the frequent patterns I'll be seeing is having to add some context vars a la extra_context. Presently I'm adding a render_response to the subclassed view and doing it there, might be nice to support a get_context_vars()

I think views as classes is a huge feature, might be nice to have the generic views inherit from a BaseView? and BasePaginate? view, etc. Personally the application I'm working on has a lot of pages with forms that filter the view somehow, so there will be a huge number of view subclasses.

06/10/08 11:10:02 changed by jezdez

  • cc changed from floguy@gmail.com, larlet@gmail.com to floguy@gmail.com, larlet@gmail.com, jannis@leidel.info.

07/02/08 09:35:52 changed by telenieko

  • owner changed from nobody to telenieko.
  • status changed from new to assigned.
  • milestone set to post-1.0.

Is anybody working on the docs for this? If not I'll try to give it some time later. (No need to reply "no", just reply if "yes" ;))

07/08/08 11:55:03 changed by telenieko

  • attachment DjangoGenericViews.png added.

class hierarchy

07/08/08 11:57:17 changed by telenieko

Attached a possible class hierarchy. Not that what is drawn as class members are what would be passed to call() as parameters (it was easier to draw it this way).

07/31/08 15:56:24 changed by telenieko

For anyone interested in this ticket (scheduled post-1.0) current code (in-progress) can be taken from my git branch, raw, non-colored diff here.

Current code should be usable (passes tests). And provides wrappers to the old views, so if you can; Try the patch without touching your urls and let me know what happens.

08/16/08 13:06:02 changed by benjixx

  • cc changed from floguy@gmail.com, larlet@gmail.com, jannis@leidel.info to floguy@gmail.com, larlet@gmail.com, jannis@leidel.info, benjixx.

(follow-up: ↓ 19 ) 08/19/08 04:49:29 changed by telenieko

Question of the day, mostly for jacob and jkocherhans (it's DDN):

  • Would you agree to add to DetailView? and ListView? (see current diff) an extra option: "allow_serialization" (and maybe "serialization_format='json'") and then, in the call() do:
  if request.is_ajax() and self.allow_serialization:
    return serialized_stuff()

This is a pretty common pattern (if the request is AJAX return the object_list, or the object serializaed) and actually requires doing wrappers, and with this ticket would mean people needing to do their own classes, so it would be nice to provide this (disabled by default).

It's generic! and simple, and disabled by default, but avoids needing wrappers/inheritance to get such a common thing ;) (Would also allow YUI, dojo, etc to provide better integration as there would be a standard way to get data for grids, etc from django).

(in reply to: ↑ 18 ) 08/19/08 12:51:03 changed by jkocherhans

Replying to telenieko:

Question of the day, mostly for jacob and jkocherhans (it's DDN): * Would you agree to add to DetailView? and ListView? (see current diff) an extra option: "allow_serialization" (and maybe "serialization_format='json'") and then, in the call() do:

This seems more in the realm of the various REST projects going on, so I'd be -0. People are going to want to control which fields are serialized, and that is definitely out of scope for DetailView and ListView.

(follow-up: ↓ 21 ) 08/20/08 07:33:52 changed by R. Bailey <bailey@akamai.com>

is the definition for ObjectListView? not committed to base.py? I don't know how to use git yet, perhaps I'm missing something.

(in reply to: ↑ 20 ) 08/20/08 07:40:26 changed by telenieko

Replying to R. Bailey <bailey@akamai.com>:

is the definition for ObjectListView? not committed to base.py? I don't know how to use git yet, perhaps I'm missing something.

I assume you refer to the imports in django/views/generic/list_detail.py, that was a typo I renamed ObjectListView? and ObjectDetailView? to ListView? and DetailView? to make them shorter.

Thanks for spotting the typo, that means there are more tests needed ;)

08/20/08 07:59:53 changed by R. Bailey <bailey@akamai.com>

good deal, thanks. I'll sync up.

(follow-up: ↓ 27 ) 09/04/08 09:39:40 changed by telenieko

With 1.0 on the streen it's time to start with the killer features for 1.1 (yes I intend this one to go for 1.1 ehehe).

Question one: Would you love a ListEditView?() which used FormSets? to edit/create multiple objects? (Just like an EditView? but for more than one form).

Question mostly for Jacob: The documentation for the class based generic views (see current docs diff) has to document all the methods available for inheritance which makes the document itself a bit cumbersome (lots of details that people wanting to "just use" those views are not interested in). So, would it be reasonable to do a topics/generic-views.txt with the introduction and the usage details; And then put on ref/generic-views.txt the implementation details and how can one inherit/develop generic views on top of the new ones?

09/04/08 10:01:09 changed by david

That's my main goal for 1.1 too. I hardly can find time for now but I keep an eye on it. Thanks for taking this.

09/15/08 10:18:12 changed by carljm

  • cc changed from floguy@gmail.com, larlet@gmail.com, jannis@leidel.info, benjixx to floguy@gmail.com, larlet@gmail.com, jannis@leidel.info, benjixx, carl@dirtcircle.com.

09/21/08 10:07:47 changed by jezdez

  • cc changed from floguy@gmail.com, larlet@gmail.com, jannis@leidel.info, benjixx, carl@dirtcircle.com to floguy@gmail.com, larlet@gmail.com, benjixx, carl@dirtcircle.com, jezdez.

(in reply to: ↑ 23 ) 09/22/08 14:44:59 changed by telenieko

For the record, from IRC conversation:

Replying to telenieko:

Would you love a ListEditView?() which used FormSets? to edit/create multiple objects? (Just like an EditView? but for more than one form).

That would be another ticket after this one gets in.

Would it be reasonable to do a topics/generic-views.txt with the introduction and the usage details; And then put on ref/generic-views.txt the implementation details and how can one inherit/develop generic views on top of the new ones?

Jacob is planning to do so for current generic views, so I'll do so for those ones.

11/25/08 22:53:32 changed by anonymous

  • cc changed from floguy@gmail.com, larlet@gmail.com, benjixx, carl@dirtcircle.com, jezdez to floguy@gmail.com, larlet@gmail.com, benjixx, carl@dirtcircle.com, jezdez, kyle.fox@gmail.com.

12/26/08 02:17:19 changed by sciyoshi

  • cc changed from floguy@gmail.com, larlet@gmail.com, benjixx, carl@dirtcircle.com, jezdez, kyle.fox@gmail.com to floguy@gmail.com, larlet@gmail.com, benjixx, carl@dirtcircle.com, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com.

01/19/09 12:51:46 changed by carljm

  • cc changed from floguy@gmail.com, larlet@gmail.com, benjixx, carl@dirtcircle.com, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com to floguy@gmail.com, larlet@gmail.com, benjixx, carljm, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com.

01/29/09 07:56:51 changed by vbmendes

  • cc changed from floguy@gmail.com, larlet@gmail.com, benjixx, carljm, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com to floguy@gmail.com, larlet@gmail.com, benjixx, carljm, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com, vbmendes@gmail.com.

02/25/09 13:51:44 changed by

  • milestone deleted.

Milestone post-1.0 deleted

02/28/09 13:46:17 changed by jacob

  • milestone set to 1.1 beta.

03/10/09 09:38:11 changed by Anossov

  • cc changed from floguy@gmail.com, larlet@gmail.com, benjixx, carljm, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com, vbmendes@gmail.com to floguy@gmail.com, larlet@gmail.com, benjixx, carljm, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com.

03/19/09 17:12:17 changed by david

  • cc changed from floguy@gmail.com, larlet@gmail.com, benjixx, carljm, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com to floguy@gmail.com, david, benjixx, carljm, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com.

03/23/09 18:28:51 changed by jacob

  • milestone changed from 1.1 beta to 1.2.

Looks like this won't make it; I didn't get it done.

(follow-up: ↓ 38 ) 04/09/09 16:06:50 changed by mmalone

  • cc changed from floguy@gmail.com, david, benjixx, carljm, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com to floguy@gmail.com, david, benjixx, carljm, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com, mjmalone@gmail.com.

I think documenting the use of class-based views and providing a simple implementation would be a great addition to Django, but I don't think this is the right approach.

I've seen two methods of implementing class-based views, __call__ based and __init__ based. The attached patch uses the __call__ approach. Here's a quick example of an __init__ based class-view:

from django.http import HttpResponse

class BaseView(HttpRespones):
    def __init__(self, request, *args, **kwargs):
        content = self.get(*args, **kwargs)
        super(MyView, self).__init__(content)

    def get(self):
        return 'Hello, world!'

The big gain here is that Django will instantiate a view instances per request, so you can actually store state in view objects. The __call__ based approach can be misleading/dangerous/confusing in this respect since the view instance is a global object that will be retained between requests. Even if you reset the state of the object at the beginning of each request, it's process local so it isn't thread safe.

The only thing the __init__ approach complicates is passing default arguments in during instantiation (e.g., model and post_save_redirect in the attached patch), but the url() function already solves that problem for function-based views by providing the kwargs argument, which works equally well here.

Unless anyone can think of some benefit to using the __call__ approach, I'd suggest we use __init__ instead.

(in reply to: ↑ 37 ) 04/10/09 15:42:59 changed by telenieko

Replying to mmalone:

I've seen two methods of implementing class-based views, __call__ based and __init__ based. The attached patch uses the __call__ approach. Here's a quick example of an __init__ based class-view:

Hi mmalone, This is getting a major re-thing/re-write by Jacob, taking an approach much more like Model classes, if I remember correctly, the thing was something like:

from django.views.generic import ListView

class MyListView(ListView): 
    # Base view for views that list objects
    queryset = MyModel.objects.all() 
    paginate_by = 30    
    # You may override some methods here.

Then you'd pass the MyListView? class to the URL patterns. init() would get URL parameters, while view configuration (what the current code here passes to init() would be on the class definition.

It's much more like Model classes, the only drawback is that you need to define you view class even for really simple stuff. But complex things get much nicer ;)

Hope Jacob can push current code sometime soon for everyone to see.

Thanks for commenting!

(follow-up: ↓ 42 ) 04/10/09 15:45:33 changed by Alex

Jacob's code is on github account.

(follow-up: ↓ 43 ) 04/10/09 15:59:18 changed by mmalone

Anyone have a link to Jacob's code on github? I checked his projects but couldn't find it easily.

telenieko: re simple things becoming harder, you'll still be able to make function-based views so that's not really true!

04/10/09 16:01:05 changed by carljm

(in reply to: ↑ 39 ) 04/10/09 16:18:57 changed by telenieko

Replying to Alex:

Jacob's code is on github account.

Thanks! I should do "git remote update" more often :)

(in reply to: ↑ 40 ; follow-up: ↓ 44 ) 04/10/09 16:20:14 changed by telenieko

Replying to mmalone:

telenieko: re simple things becoming harder, you'll still be able to make function-based views so that's not really true!

I think those will be deprecated in favour of the class based ones.

(in reply to: ↑ 43 ) 04/10/09 16:30:44 changed by mmalone

Replying to telenieko:

I think those will be deprecated in favour of the class based ones.

That's kind of dumb. Django has always supported both, why explicitly "deprecate" one method when they're both well supported.

Also, I just took a look at Jacob's code and it looks like he's using the __call__ based approach, so my comments from above still apply. If you tell someone to write a class they're going to want to store state in instances, and I think that's going to be problematic.

04/10/09 16:44:21 changed by Alex

Mike, he means the function generic views will be deprecated, not views in general.

04/10/09 19:04:24 changed by mmalone

Ah, ok. That makes more sense.

05/19/09 00:46:59 changed by anonymous

  • cc changed from floguy@gmail.com, david, benjixx, carljm, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com, mjmalone@gmail.com to floguy@gmail.com, david, benjixx, carljm, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com, mjmalone@gmail.com, taavi@taijala.com.

08/20/09 00:53:33 changed by narma

  • cc changed from floguy@gmail.com, david, benjixx, carljm, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com, mjmalone@gmail.com, taavi@taijala.com to floguy@gmail.com, david, benjixx, carljm, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com, mjmalone@gmail.com, taavi@taijala.com, narma.nsk@gmail.com.

12/12/09 09:26:17 changed by Nate

I've just been poking through the branch on GitHub? and it looks great, but just in the name of API consistency it looks like the API for the class based views does not match the API for Syndication Feeds.

Namely, in a feed, if you want to override (for example) 'title' you can either provide a method or a string and the feed will handle either value intelligently.

In the class based views (so far), if you want to override (for example) 'items' you can either set 'items' or you can override the method get_items. This isn't consistent.

I'm not sure if this is an issue but I thought I'd point it out.

12/29/09 03:57:51 changed by obeattie

  • cc changed from floguy@gmail.com, david, benjixx, carljm, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com, mjmalone@gmail.com, taavi@taijala.com, narma.nsk@gmail.com to floguy@gmail.com, david, benjixx, carljm, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com, mjmalone@gmail.com, taavi@taijala.com, narma.nsk@gmail.com, obeattie.

12/30/09 02:11:18 changed by kylefox

  • cc changed from floguy@gmail.com, david, benjixx, carljm, jezdez, kyle.fox@gmail.com, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com, mjmalone@gmail.com, taavi@taijala.com, narma.nsk@gmail.com, obeattie to floguy@gmail.com, david, benjixx, carljm, jezdez, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com, mjmalone@gmail.com, taavi@taijala.com, narma.nsk@gmail.com, obeattie.

01/03/10 18:52:14 changed by darkpixel

  • cc changed from floguy@gmail.com, david, benjixx, carljm, jezdez, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com, mjmalone@gmail.com, taavi@taijala.com, narma.nsk@gmail.com, obeattie to floguy@gmail.com, david, benjixx, carljm, jezdez, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com, mjmalone@gmail.com, taavi@taijala.com, narma.nsk@gmail.com, obeattie, darkpixel.

01/22/10 05:37:57 changed by Ciantic

  • cc changed from floguy@gmail.com, david, benjixx, carljm, jezdez, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com, mjmalone@gmail.com, taavi@taijala.com, narma.nsk@gmail.com, obeattie, darkpixel to floguy@gmail.com, david, benjixx, carljm, jezdez, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com, mjmalone@gmail.com, taavi@taijala.com, narma.nsk@gmail.com, obeattie, darkpixel, Ciantic.

02/02/10 15:28:34 changed by unbracketed

  • cc changed from floguy@gmail.com, david, benjixx, carljm, jezdez, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com, mjmalone@gmail.com, taavi@taijala.com, narma.nsk@gmail.com, obeattie, darkpixel, Ciantic to floguy@gmail.com, david, benjixx, carljm, jezdez, sciyoshi@gmail.com, vbmendes@gmail.com, anossov@gmail.com, mjmalone@gmail.com, taavi@taijala.com, narma.nsk@gmail.com, obeattie, darkpixel, Ciantic, brian@unbracketed.com.

02/10/10 07:48:34 changed by russellm

  • version deleted.
  • milestone deleted.

Add/Change #6735 (Class-based generic views)




Change Properties
Action