Opened 4 years ago

Last modified 2 years ago

#20941 new New feature

Provide a way for CBVs to be called from instances

Reported by: Marc Tamlyn Owned by: Marc Tamlyn
Component: Generic views Version: master
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


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 (4)

comment:1 Changed 4 years ago by Tim Graham

Triage Stage: UnreviewedAccepted
Version: master

comment:2 Changed 2 years ago by Tom Christie

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 Changed 2 years ago by Marc Tamlyn

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':}
self.assertEqual(view.get_object(), book)

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

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

comment:4 Changed 2 years ago by Collin Anderson

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

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