Reputation:
Are def post
and if.request.method == POST
the same?
I've seen some using def post(self, request)
and some using if.request.method == 'POST'
. They both seem to work, at least for the tasks I've seen.
Is there difference?
Upvotes: 5
Views: 5307
Reputation: 2671
I think you mixed 2 main Django approaches: function-based views and class-based views.
if request.method == POST
- FBV,
def post(self, request)
- CBV.
In FBV you usually write views as functions, where conditionally check what method was made. In CBV you are overriding some Django built-in classes and built-in methods in that classes.
And yes, this is the same action.
P.S. For beginners it is easier to start learning Function Based Views.
Upvotes: 10
Reputation: 477308
I assume you are talking about class-based views. In that case, if you do not change the routing mechanism, the answer is yes.
Let us look at the source code of the View
class [GitHub]. Usually class-based views subclass from this class, and thus inherit the behavior of this class:
class View: # ... http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] # ... @classonlymethod def as_view(cls, **initkwargs): # ... def view(request, *args, **kwargs): self = cls(**initkwargs) if hasattr(self, 'get') and not hasattr(self, 'head'): self.head = self.get self.request = request self.args = args self.kwargs = kwargs return self.dispatch(request, *args, **kwargs) # ... return view def dispatch(self, request, *args, **kwargs): # ... if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed return handler(request, *args, **kwargs) # ...
I here stripped away parts that are more or less irrelevant, and fixed the formatting a bit to make it more convenient to read.
As you can see, if you call the as_view()
function (when you declare a url(..)
or path(..)
, then it basically constructs a function def view(..)
that, and a reference to that function is linked with this URL.
Now the view(..)
function, performs some operations (for example if the head (...)
function is not implemented, it will later fallback on the get (..)
function. The most important part is however that it calls the self.dispatch(..)
function.
This dispatch function looks to the request.method
. It converts this method to a lowercase variant, and then checks if that method is declared in the view. If it is, it will call the corresponding method (so in case request.method == 'POST'
, it will call post (...)
with request
, *args
, and **kwargs
), and if the method is missing, it will basically return a "HTTP method not allowed response".
Note however that you can subclass the as_view
, and dispatch(..)
function, and thus change this behavior.
Furthermore strictly speaking, you can write your own View
class, that of course can have totally different behavior, but I assume that this is not really the scope of this question.
The class-based view thus basically performs something like (this is not how the code looks like, but semantically it is approximately the same as):
def some_view(request, *args, **kwargs):
if request.method == 'GET':
return self.get(request, *args, **kwargs)
if request.method == 'POST':
return self.post(request, *args, **kwargs)
if request.method == 'PUT':
return self.put(request, *args, **kwargs)
if request.method == 'PATCH':
return self.patch(request, *args, **kwargs)
if request.method == 'DELETE':
return self.delete(request, *args, **kwargs)
if request.method == 'HEAD':
return self.head(request, *args, **kwargs)
if request.method == 'OPTIONS':
return self.options(request, *args, **kwargs)
if request.method == 'TRACE':
return self.trace(request, *args, **kwargs)
else:
return self.http_method_not_allowed(request, *args, **kwargs)
given of course all these functions exists (that is not always the case). Furthermore the options(..)
function is generated automatically: it inspects what functions are defined, and returns a list of the corresponding methods.
Upvotes: 2