Reputation: 219
I will keep this question short. Similar questions on S/O do not address what I am wondering about, and I have struggled to find an answer.
When I point to a CBV in my urls.py, I use the as_view class method:
...MyView.as_view()...
Looking at the actual script (django/django/views/generic/base.py), the as_view returns a function 'view' that is specified within the actual class method itself. How come it returns the function with this line:
return view
Why does it not have to specify:
return view(request, *args, **kwargs)
I tried this out myself. I went and created a FBV_1 that returned yet another FBV_2 (the view responsible for delivering all functionality), in this same manner:
return fbv_2
It generated an error. I had to return fbv_2(request) to access it.
Thank you in advance. Apologies for any idiomatic expression-errors, my Swedish sometimes gets the best of me.
Upvotes: 0
Views: 847
Reputation: 11879
"view" is the function name name.
In this case we have defined the function within another function - as_view(). Think of the name "view" as a variable pointing to code rather than data.
view
is the function - we have defined it (within the as_view() function). It already knows what arguments to expect from the line:
def view(request, *args, **kwargs):
...
..
A function is just code.
To execute the function you would usually type the function name followed by parenthesis enclosing any arguments.
view(request, kwarg1=var1 , kwarg2=var2)
calls the function called view and executes the code.
I hope that makes sense. Its not difficult, but a bit tricky to describe.
Upvotes: 1
Reputation: 8506
You're missing some important details in your investigation:
The as_view()
class method never takes hold of the request object or function arguments, it just returns a callable for the function it declares in its definition. Returning a callable is different to returning an object or in this case, a Response object. When an url
object is evaluated, your code does something like the following, let's make some URL objects:
url(r'/some_pattern/', views.some_view)
url(r'/other_pattern/', views.ClassBasedView.as_view())
when I go to /some_pattern
, some_view
is defined as a callable, so it can be executed as a function:
views.some_view(request, *args, **kwargs)
when I go to /other_pattern/
, the class-based view is expected to return a callable after as_view()
, which it does:
views.ClassBasedView.as_view()(request, *args, **kwargs)
this is evaluated to:
view(request, *args, **kwargs)
which in turn is evaluated to:
self.dispatch(requests, *args, **kwargs)
where self
is an instance of ClassBasedView, and dispatch always returns an HttpResponse of some sort:
HttpResponse('hello!')
So! after all this, if you don't see how your premise is faulty, let's complete your test, you have the following:
def fbv_2(request, *args, **kwargs):
return HttpResponse('hello!')
def fbv_1(request, *args, **kwargs):
return fbv_2
and the following URL definition:
url(r'/test/', views.fbv_1)
Then, when I point my browser to /test/
:
views.fbv_1(request, *args, **kwargs)
which is evaluated to
views.fbv_2
Uhm, so what happened? well, the Handler expected some sort of HttpResponse, but instead received a function pointer, which he wont evaluate. You see, the as_view()
method is what we call a Factory, its job is to create view functions based on what the class defines as instance methods, because the Handler can't understand instance methods, just functions.
Upvotes: 1
Reputation: 1187
All functions in Python are first-class objects. You don`t have to call it before return, you can do whatever operations you like with functions without calling them, you can even set attrs for functions:
func.level = 5
The difference is just when you call function on return, function response would be returned, and when don't the function itself is returned. Basically, is_view method returns the same view function as you would`ve written in your views.py:
def view(request):
...
return HttpResponse(...)
As you can see it always has request as the first param.
Upvotes: 0