Search code examples
djangodjango-rest-viewsetsdjango-viewsets

Cannot get values from request in Django - Empty QueryDict


I’m new to ViewSets and am trying to get the values sent from the front-end fetch method to Django’s request object in the create function. I don’t know whether it’s just a simple syntax error or whether the data isn’t being sent properly from the front-end, but I think it’s a back-end issue.

The stringified data in the post method seems to log correctly at the front-end like with this test:

{"title":"test","type":"landing","slug":"","notes":""}

Printing variables in the ViewSet’s create function however shows these:

print(request.POST["title"]) # fails with keyerror: 'title' MultiValueDictKeyError(key) django.utils.datastructures.MultiValueDictKeyError: 'title'
print(request["title"]) # fails with TypeError: 'Request' object is not subscriptable
print(request.POST.get("title", “test”)) # fails as print test
print(request.POST.get("title")) # fails as it just returns None
print(request.get("title")) # fails with AttributeError: 'WSGIRequest' object has no attribute 'get'
print(self.request.query_params.get("title", None)) # prints None
print(self.request.query_params)  # prints empty QueryDict: <QueryDict: {}>

Here’s the create function:

class PagesViewSet(viewsets.ViewSet):
    def create(self, request):
    # printing went here
        page = Page.objects.create(
            title="testing", type="other", slug="test-slug", notes="test notes"
        )
        serializer = PageSerializer(page)
        return Response(serializer.data)

I’ve just chucked in demo data inside the page create method to ensure it works, which it does, and now want to use the real data which should be in the request.

Does anyone know what might be the issue here?

For visibility, here’s the front-end API-request function:

const createPage = async (data: CreatePageFormInputs) => {
    console.log('stringified: ', JSON.stringify(data)); // logs correctly
    const res = await fetchCreatePage('http://localhost:8000/api/pages/', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data),
    });
};

Maybe irrelevant but in case you're wondering what fetchCreatePage is, it's just this part of a custom react hook:

const fetchCreatePage: FetchDataFn = async (url, options?) => {
        const setFailed = () => {
            setFetchError(true);
            setLoading(false);
        };
        const setSuccess = (data: any) => {
            setData(data);
            setLoading(false);
        };

        try {
            setLoading(true);
            const res = await fetch(url, options);

            if (!res.ok) {
                console.log('Error detected. Returning...');
                setFailed();
                return;
            }

            if (res.status === 204) {
                setSuccess({
                    success: true,
                    info: 'Item successfully deleted',
                });
                return;
            }

            const data = await res.json();
            setSuccess(data);
        } catch (e) {
            setFailed();
        }
    }

I assume the POST method is correct. Any help would be appreciated, thanks.


Solution

  • You wrote the data as body of the request in a JSON format. You thus should decode the JSON format to a dictionary with:

    import json
    
    data = json.loads(request.body)
    print(data['title'])

    If you are using a request from the Django REST framework, you work with request.data:

    import json
    
    print(request.data['title'])

    request.data will look for POST parameters and a JSON body.