Opened 11 years ago

Closed 4 years ago

#20941 closed New feature (duplicate)

Provide a way for CBVs to be called from instances

Reported by: Marc Tamlyn Owned by: Marc Tamlyn
Component: Generic views Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

With the changes in the dispatch method to make overriding the method easier, we lost the ability to easily instantiate and call a class based view directly. There are some custom use cases where this is useful - and it's generally useful in tests. The end user perhaps has to be careful about thread safety, but nonetheless.

Ideally this would be callable after __init__() so the view instance can have some processing done before the request is known.

This would also be useful for providing better ways to test the CBVs.

Change History (5)

comment:1 by Tim Graham, 11 years ago

Triage Stage: UnreviewedAccepted
Version: master

comment:2 by Tom Christie, 9 years ago

Okay, so what am I missing here?

request = self.factory.get('/')
response = MyView.as_view()(request)

What use case or functionality is this feature request trying to address that isn't covered by the above?

comment:3 by Marc Tamlyn, 9 years ago

That's not an instance! as_view() gives an opaque function with no access to the instance of the class, so we can't test parts of it individually.

The change in the dispatch method I mentioned means that the following code currently does not work as you might expect (in particular, self.args is not set):

request = self.factory.get('/')
view = MyView(**initkwargs)
response = view.dispatch(request, *args, **kwargs)

I acknowledge that this is perhaps not that different from calling as_view(), but having an API along the lines of MyView().setup_request(request, *args, **kwargs) would allow more atomic testing of class based views in a nicer fashion. Compare below:

# current
book = Book.objects.create(...)
view = BookDetail()
view.request = request
view.args = ()
view.kwargs = {'pk': book.pk}
self.assertEqual(view.get_object(), book)

# possible better version
book = Book.objects.create(...)
view = BookDetail().setup_request(request, pk=book.pk)
self.assertEqual(view.get_object(), book)

It's not a big difference, but in my opinion it's a nice one.

comment:4 by Collin Anderson, 9 years ago

If it helps, you can now introspect the view class and args from the as_view() function. #24055

comment:5 by Baptiste Mispelon, 4 years ago

Resolution: duplicate
Status: newclosed

#29750 introduced View.setup() which seems to be exactly what Marc proposed in his comment (with the name setup_request).

Note: See TracTickets for help on using tickets.
Back to Top