William Zimmermann
William Zimmermann

Reputation: 916

How to receive an POST request from Django Rest Framework?

I build a API usign Django 2 and Django Rest Framework. All get methods are ok, using authentication first to receive a token and using this token to access all the other methods. The only problem is with the only function that I have that receive a POST data.

The problem is that the call for this POST method allways return, even providing the "authorization" token, this message:

"{"detail":"Authentication credentials were not provided."}

The funy thing is that in POSTMAN it works! Another developer tried with JavaScript and it allways return this message. I tried with PHP making a POST request using CURL and give the same error. Just with POSTMAN it works...

This is my Django Rest Framework settings in settings.py:

INSTALLED_APPS = [
    ...
    'rest_framework.authtoken',
    ...
]
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
}

This is the method called trought API, in views.py:

@api_view(['POST'])
def api_inventory_sector_items_check(request, branch_id, inventory_id, sector_id):
    # Do something

This is the url.py:

# ...
from rest_framework.urlpatterns import format_suffix_patterns
# ...
urlpatterns = [
    ...   
    path('.../check', # See the long URL bellow
    views.api_inventory_sector_items_check,
    name='app.api.inventory_sector_items_check'),
]
# ...

So I'm trying to call using POST:

{{domain}}/app/api/v1/branches/1/inventories/2/sectors/100101329/items/check

'Content-Type: application/json'

'Authorization: Token Token efad3303547374b7c035499218ad5d0cceb03178'

And in the body posting some data...

As I told before, using POSTMAN all it's ok. But when we try to submit this post by any other 'method', it returns the same message. Detail: with the same HEADER, but for GET requests, all works.

Follow a example of request using PHP that returns "... credentials were not provided".

<?php
$data = array(
"data"=>"{'id':'20012738', 'obs': '', 'resp':'325880','final':1}",
);        
                                        
$data_string = json_encode($data);                                                                                   

$ch = 
curl_init('http://localhost/app/api/v1/branches/1/
inventories/7/sectors/100162162/items/check');                                                                  
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");                                                                     
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);                                                                  
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);                                                                      
curl_setopt($ch, CURLOPT_HTTPHEADER, array(                                                                          
    'Content-Type: application/json',                                                                                
    'Content-Length: ' . strlen($data_string)),
    'Authorization: Token efad3303547374b7c035499218ad5d0cceb03178'                           
);                                                                                                                   

$result = curl_exec($ch);
echo $result;
?>

Someone can help me? Thank you very much!

Upvotes: 1

Views: 4016

Answers (2)

William Zimmermann
William Zimmermann

Reputation: 916

My PHP code to submit was wrong and Will Kelling help me. Thank you. Anyway, to submit POST data for Django Rest API was retourning no data... I solved this problem by use:

request.body

instead

request.POST.get('data')

Then, my code become like this:

@api_view(['POST'])
def api_inventory_sector_items_check(request, branch_id, inventory_id, sector_id):
        try:
            sector_items = request.body
            except Exception:
                return Response({"detail": "No data received or isn't a JSON data"}, status=status.HTTP_406_NOT_ACCEPTABLE)

        try:
            sector_items = json.loads(sector_items)
        except json.JSONDecodeError or TypeError:
            return Response({
                'detail': "Data received has a wrong format. This is not a JSON var."
            }, status=status.HTTP_404_BAD_REQUEST)

Upvotes: 1

Will Keeling
Will Keeling

Reputation: 23004

You have a subtle typo in:

curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/json',
    'Content-Length: ' . strlen($data_string)),
    'Authorization: Token efad3303547374b7c035499218ad5d0cceb03178'
);  

The array() ends before the Authorization header is added (note the closing parenthesis at the end of the content-length header). That will prevent the token from being transmitted correctly, and will likely cause the authentication error.

Change to:

curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/json',
    'Content-Length: ' . strlen($data_string),
    'Authorization: Token efad3303547374b7c035499218ad5d0cceb03178')
);  

Upvotes: 1

Related Questions