Get JSON data from POST in Django with REST Framework

15,031

Solution 1

If you are using Django REST framework then you can easily get the data from the request object by accessing the request.data dictionary (more info here).

If you are using a vanilla Django view then you can access POST data by using the request object and accessing request.POST['<field_name>'] or request.POST.get('<field_name>').

For example:

request.POST.get("date")

You can read more about that or look at examples here.

Solution 2

To get an parameter in Json format you need change the submethod of request from "GET" to "DATA", like this:

sheet = request.data.get("sheet")

Solution 3

Try this:

request.data.get("sheet")
Share:
15,031
Yannick
Author by

Yannick

Updated on June 27, 2022

Comments

  • Yannick
    Yannick almost 2 years

    I am attempting to build a REST API in Django for a Google Spreadsheet with Gspread, I'm running into a lot of issues (so if anyone happens to have a full example lying around, feel free to share... please? :)). One of those issues it that I'm trying to receive JSON for a POST request (and later on other requests, of course). This is, however, failing. This is my code:

    view.py (I'm aware that that IF-statement is not how it works

    elif request.method == 'POST':
        received_json_data = json.loads(request.body.decode("utf-8"))
        content = received_json_data['content']
        if content != "":
            worksheet.insert_row([content["date"], content["days"], content["firstname"], content["lastname"], content["team"], content["training"], content["company"], content["city"], content["cost"], content["invoice"], content["info"]], 1)
            return JsonResponse(content, safe=False, status=status.HTTP_201_CREATED)
        else:
            return JsonResponse([], safe=False, status=status.HTTP_400_BAD_REQUEST)
    

    A test that has been written for this:

    def test_post_all_training_returns_201_when_correct_format(self):
        """
        A POST request on /trainings/ should create a new training
        """
        headers = {'content-type': 'application/json'}
        response = self.client.post('/trainings/', json=json.dumps(self.training_json_body), headers=headers, format="json")
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
    

    The contents of the training_json_body:

    self.training_json_body = {
        "date": "1/1/2018",
        "days": 1,
        "firstname": "Data",
        "lastname": "Data",
        "team": "Data",
        "training": "Data",
        "company": "Data",
        "city": "Data",
        "cost": 1,
        "invoice": "Data",
        "info": "Data"
    }
    

    Traceback

    Traceback (most recent call last):
    File "C:\Python\backend\unleashedapp\trainings\tests.py", line 64, in test_post_all_training_returns_201_when_correct_format
        response = self.client.post('/trainings/', json=json.dumps(self.training_json_body), headers=headers, format="json")
    File "C:\Users\yanni\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\test\client.py", line 525, in post
        response = super().post(path, data=data, content_type=content_type, secure=secure, **extra)
    File "C:\Users\yanni\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\test\client.py", line 341, in post
        secure=secure, **extra)
    File "C:\Users\yanni\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\test\client.py", line 404, in generic
        return self.request(**r)
    File "C:\Users\yanni\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\test\client.py", line 485, in request
        raise exc_value
    File "C:\Users\yanni\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\handlers\exception.py", line 35, in inner
        response = get_response(request)
    File "C:\Users\yanni\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\handlers\base.py", line 128, in _get_response
        response = self.process_exception_by_middleware(e, request)
    File "C:\Users\yanni\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response
        response = wrapped_callback(request, *callback_args, **callback_kwargs)
    File "C:\Users\yanni\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
        return view_func(*args, **kwargs)
    File "C:\Python\backend\unleashedapp\trainings\views.py", line 36, in training_list
        received_json_data = json.loads(request.body.decode("utf-8"))
    File "C:\Users\yanni\AppData\Local\Programs\Python\Python36-32\lib\json\__init__.py", line 354, in loads
        return _default_decoder.decode(s)
    File "C:\Users\yanni\AppData\Local\Programs\Python\Python36-32\lib\json\decoder.py", line 339, in decode
        obj, end = self.raw_decode(s, idx=_w(s, 0).end())
    File "C:\Users\yanni\AppData\Local\Programs\Python\Python36-32\lib\json\decoder.py", line 357, in raw_decode
        raise JSONDecodeError("Expecting value", s, err.value) from None
    json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
    

    I have searched for a solution for a couple of days now but can't get it to work, so I would be really greatful if someone could push me in the right direction.


    I have updated my code to the following:

    class TrainingList(APIView):
        def post(self, request, format=None):
            sheet = request.GET.get('sheet', 'Data')
            worksheet = spreadsheet.worksheet(sheet)
            worksheet.append_row([request.data.get("date"), request.data.get("days"), request.data.get("firstname"), request.data.get("lastname"), request.data.get("team"), request.data.get("training"), request.data.get("company"), request.data.get("city"), request.data.get("cost"), request.data.get("invoice"), request.data.get("info")])
            return JsonResponse("[]", safe=False, status=status.HTTP_201_CREATED)
    

    This no longer throws any errors, but append_row() function is now adding "None" for every field, so clearly the data is still not going through. How can I fix this?

    • Alasdair
      Alasdair over 6 years
      I don't think you need json.dumps() in json=json.dumps(self.training_json_body). Try json=self.training_json_body.
    • Alasdair
      Alasdair over 6 years
      This is, however, failing - What is failing? Where is it failing? What do you expect to happen at that point?
    • Yannick
      Yannick over 6 years
      Sorry, I forgot to include the traceback, it is now. Removing the json.dumps doesn't work.
    • Alasdair
      Alasdair over 6 years
      What is the traceback if you remove json.dumps()? What is the value of request.body.decode("utf-8") which is causing json.loads() to fail?
  • Alasdair
    Alasdair over 6 years
    request.DATA is a good suggestion. However request.POST isn't going to work for json data, it only works for form encoded data.
  • Yannick
    Yannick over 6 years
    I've made a number of changes to use request.data (see post) but it appears to be empty for my request <QueryDict: {}>. I'm honestly not even sure I did this correct if it would actually contain something.