est
est

Reputation: 11875

django class based view returns empty string when POST

To demostrate:

from django.views.generic.base import View
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator

class TestView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return HttpResponse('haha')

urls.py is

url(r'^test/', TestView.as_view()),

so when GET you can see haha, but when doing POST you get a blank page...

What am I missing here?

Edit: To clarify what I am doing. I am writing a JSON stream CURD view, which I need to parse JSON in various ways. One of them is when ppl POST data with certain pattern the view will dispatch to another method inside the view and return something. But it turns out returns nothing instead. So I present you the minimal PoC. Please help me what my code wenti wrong. TIA!

btw possible related question

Upvotes: 0

Views: 4231

Answers (4)

est
est

Reputation: 11875

Sorry guys, this is a bug in uWSGI and nginx ...

https://stackoverflow.com/a/11115108/41948

I am really sorry for wasting your time by misleading you. And still it took me a while to figure which part of my stack went wrong.

Upvotes: 0

Dashdrum
Dashdrum

Reputation: 667

I know this doesn't really answer your question, but it may offer a workaround. What I have used in JSON applications is to send a post to the get method when I want the same results for both. Something like:

def get(self, request, *args, **kwargs):
    return HttpResponse('Ha!')

def post(self. request, *args, **kwargs):
    return self.get(request, *args, **kwargs)

with dispatch left alone.

Upvotes: 1

Berislav Lopac
Berislav Lopac

Reputation: 17243

The best approach when using class-based views is not to write your own method handlers from scratch; instead, use one of the generic classes as the base and then modify just the methods which handle what you need. For example, if you have a form which needs to be submitted via POST, you should use the FormView as a base, which handles responses both GET and POST requests.

You don't need to override post() and/or get() methods themselves; instead use form_valid() to define what happens when the form is submitted:

class TestView(FormView):
    form_class = MyForm
    success_url = "/your/return/url/"
    def form_valid(self, form):
        # do something
        return redirect(self.get_success_url())

Upvotes: 0

Ahsan
Ahsan

Reputation: 11832

You need to implement its post method. See Class based views.

from django.http import HttpResponse
from django.views.generic import View

class TestView(View):

    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        # do something
        return super(TestView, self).dispatch(*args, **kwargs)

    def post(self, request, *args, **kwargs):
       # do somthing

    def get(self, request, *args, **kwargs):
       return HttpResponse('Hello, World!')

See more for dispatch docs.

The default implementation will inspect the HTTP method and attempt to delegate to a method that matches the HTTP method; a GET will be delegated to get(), a POST to post(), and so on.

So previously you was disturbing the above logic, calling super will allow dispatch to delegate to post method.

Upvotes: 5

Related Questions