user9324026
user9324026

Reputation:

Are "def post" and "if.request.method == POST " the same?

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

Answers (2)

Chiefir
Chiefir

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

willeM_ Van Onsem
willeM_ Van Onsem

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

Related Questions