Search code examples
pythondjangohttpdjango-rest-frameworkdjango-views

Why does the getattr(ClassInstance, "http_method_names", []) function in django APIView return all http methods even though only GET is implemented?


I have a view being inherited by APIView and I have only implemented the GET method in it.

class MyView(APIView):
    def get(self, request, id):
        # do something

But when I call getattr(ClassInstance, "http_method_names", []) I get list of all the HTTP methods even though they are not implemented.


Solution

  • The .http_method_names [Django-doc] is an attribute that, by default lists all HTTP methods, so:

    ["get", "post", "put", "patch", "delete", "head", "options", "trace"]
    

    Normally it will always return that list, unless you override it. This can be useful if you inherit from a view that for example has defined a .post(…) method, but you don't want to expose that, like:

    class MyView(SomethingWithPostMethodView):
        http_method_names = ['get', 'head', 'options']
    
        def get(self, request, id):
            # …
            pass

    Or you could, technically speaking, expand the http_method_names list with an custom method, although I would strongly advise not to do this.

    In order to find out what methods the view implements, you can use the _allowed_methods(…), which thus checks if the corresponding .get(…) method is allowed or not.

    You thus can not introspect the methods allowed with:

    getattr(ClassInstance, "http_method_names", [])
    

    You can just create an instance and work with _allowed_methods():

    ClassInstance()._allowed_method()
    

    If ClassInstance is thus a reference to the type itself, or use ClassInstance._allowed_method() if it is a view object already.