This is a bit of a tricky thing to discuss since we've been talking
about this IRL at the sprints, and also on the list. I'll try to sum
up where we are now, but if anything isn't clear, ask.

We're currently working towards URLpatterns of the form::

    ('...', SomeView)

i.e. passing a class directly, which would be instantiated implicitly
then called.

The reason we're trying it this way is thread safety: if a view is a
class, then people *will* store state on self. So if we have single
instances in views like we do now, then we're giving folks enough rope
to hang themselves. By having each request get a fresh instance we
avoid that problem.

The other alternative we discussed was having the base view class do
something with threadlocals to make sure state saved on self is
threadsafe. I vetoed that because I hate threadlocals :)

On Fri, May 28, 2010 at 3:41 PM, Luke Plant <l.plant...@cantab.net> wrote:
> I'm sure that will work.  My main reluctance is using isinstance()
> when it isn't necessary, and having to change the definition of what a
> 'view' is when it isn't strictly necessary. (A view is no longer
> simply "a callable that takes a request and returns a response").

I *am* a bit worried by this -- I'm not sure redefining the definition
of "view" is such a good idea. "A view is a callable or a class with
callable instances" isn't nearly as simple and nice a recommendation.

> If, however, we encouraged `MyClassView.as_view()` from the start, we
> can cope with constructor arguments more easily - it changes to
> `MyClassView.as_view(somearg=something)`.

My only real objection here is that `as_view` is just a bunch of boilerplate::

    urlpatterns = patterns('',
        ('one/', SomeView.as_view()),
        ('two/', SomeOtherView.as_view()),
        ('three', YourView.as_view())
    )

I just really don't like the way that looks.

As for accepting extra __init__ arguments: I specifically *don't* want
to allow this (at least easily) because I want to encourage
subclassing as the "correct" way of extending views. Yes, this means a
slight loss of flexibility, but it also means that we're forcing
people into a more extensible and fuure-proof way of coding, and
that's a good thing.

> (Either way, it would still be possible to pass in MyClassView() and
> get thread safety problems, but it's about making mistakes less
> natural).

... and either way it's pretty easy to issue a warning if you've
subclassed ``django.views.View`` (my proposed name for the view base
class) and re-used it for multiple requests.

> There is also the issue of what to do when you need to add a decorator
> to someone else's view function.

Again, I want to encourge "subclass it" as the correct answer here.

> Given that, for many Django apps, the view functions are part of the
> public API that needs to be exported (i.e. hooked into people's
> URLconfs or wrapped for re-use), I think it would be good to encourage
> practices which will lead to stable and consistent APIs, and so *not*
> allow or encourage classes to be used directly in the URLconf.

I think we're in agreement here -- we're both trying to avoid view-ish
stuff in the URLconfs (a la the old way we used to do generic views
with dicts in urls.py).

Having played with it for a few years now, though, I'm finding
subclassing is really the best way to make this happen.

So reusable apps instead of exporting functional views export
class-based ones; users who want to re-use them import, subclass, and
extend.

Jacob

-- 
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