Django Rest get request parameters - django

Django request handler let you get POST parameters using request.DATA
def post(self, request):
request.DATA.
How could I get DELETE parameters?
I tried
def delete(self,request):
request.body
request.read()
Both request.body and request.read() just displays csrfmiddlewaretoken and _method parameters.
For both of the above example I am sending the parameters as application/json.
How could I get the delete request parameters?

I know this question is quite old, but for reference: I think you might want Request.QUERY_PARAMS. See the REST Framework docs for more info: http://django-rest-framework.org/api-guide/requests.html

Related

Django Rest Framework: How to send data to request.data

Im building a simple api in Django Rest Framework using class based views and the documentation mentions request.data (https://www.django-rest-framework.org/tutorial/2-requests-and-responses/)
from rest_framework.views import APIView
class myView(APIView):
def post(self, request):
print(request.data)
When I try to send post requests either with
curl: curl --data param1=val1&param2=val2 url
djangos browser interface with post (using formatted url and the post option
Advanced Rest Client (chrome add on)
The data of all three appears to end up in request.query_params.
When I try to print request.data, however I get an empty response {}
I could just use request.query_params, Im just curious as to how one would get data to go to request.data since it is talked about in the documentation
edit: so curl --data param1=val1&param2=val2 -X POST url sends information to request.data (now if I say request.query_params if get the empty dict {} but request.data contains an object that is the dict query_params.)
curl request doesn't have the -X and POST added.
Add these

Django REST giving a 403 forbidden on DELETE methods, but not POST

I am trying to delete an entry using an ajax call.
when I am using the default 'delete' method from generics.DestroyAPIView, I am getting a 403 Forbidden, but if I add a post method, call the delete method immediately and change the ajax type to 'post' it works fine. Would anyone have an idea what causes this?
Note that I overwrite the get_object function to get the object based on posted data. (could it be due to delete methods not allowing to post data? If so, why? And how would you pass the CSRF token??)
ajax:
$.ajax({
url: '{% url "account:api:post_details_delete" %}',
type: 'delete',
data: { csrfmiddlewaretoken: "{{ csrf_token }}", name: json.name, value: json.value }
});
url:
path('post_details/delete/', PostDetailDeleteApiView.as_view(), name='post_details_delete'),
view:
class PostDetailDeleteApiView(generics.DestroyAPIView):
serializer_class = PostDetailSerializer
# the code below allows it to work if uncommented and type in ajax changed to 'post'
# def post(self, request, *args, **kwargs):
# return self.delete(request, *args, **kwargs)
def get_object(self):
"""
Returns the post detail object to be deleted based on the name:value pair
provided by the ajax call.
"""
data = self.request.data
obj = Post_Detail.objects.filter(
name=data.get('name', ''), value=data.get('value', '')
).filter(
post__account__user=self.request.user
)
if obj.exists():
return obj.get()
else:
raise Http404
serializer:
class PostDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Post_Detail
fields = ['name', 'value']
A 403 Forbidden error code would suggest that in some way or another that either permission is denied or that you're not authenticated.
The 'DestroyAPIView' is used for delete-only API endpoints for a single model instance.
Do you have the full traceback that you can append to your question?
Docs References
Django REST Framework's Destroy API View
Django REST Framework's Guide to Permissions
According to Django documentation you must pass the csrftoken to headers of ajax request
While the above method can be used for AJAX POST requests, it has some inconveniences: you have to remember to pass the CSRF token in as POST data with every POST request. For this reason, there is an alternative method: on each XMLHttpRequest, set a custom X-CSRFToken header (as specified by the CSRF_HEADER_NAME setting) to the value of the CSRF token. This is often easier because many JavaScript frameworks provide hooks that allow headers to be set on every request.

Django - RawPostDataException: You cannot access body after reading from request's data stream

I'm really stuck at this problem for a couple of days now.
While I understand, what's happening here, I don't really know the best workaround/solution for this.
Problem:
I'm trying to create a user login endpoint using Django and DRF in general.
My login API needs to support a login via password as well as login via OTP.
My LoginView looks like:
def post(self, request, **kwargs):
"""
post
Method to handle user login
:param request:
:param args:
:param kwargs:
:return:
"""
request_data = request.data
login_using_password = request_data.get('login-with-password') is True
login_using_otp = request_data.get('login-with-otp') is True
if request_data is not None:
if all((login_using_password, login_using_otp)):
raise accounts_exceptions.InvalidLoginRequestError()
if login_using_password:
return Response(self._login_with_password(request))
elif login_using_otp:
return Response(self._login_with_otp(request))
raise accounts_exceptions.InvalidLoginRequestError()
return Response(self._login_with_password(request))
Also my _login_with_password looks like:
def _login_with_password(self, request, **kwargs):
"""
_login_with_password
A utility method to handle login with password
:param request:
:return:
"""
return getattr(ObtainJSONWebToken.as_view()(request=request._request, ), 'data')
When I try to login, Django complains saying RawPostDataException You cannot access body after reading from request's data stream
I'm using JWT to authenticate requests. ObtainJSONWebToken is a view provided by DRF-JWT to obtain access tokens to authenticate requests.
What is the workaround/solution for this?
Is there a better way to support such a login requirement?
Thanks in advance!
Resolved this.
There's no concrete way to solve the problem above.
Django disallows access to request.data multiple times.
It could be done only once for the entire request lifetime.
So, this left me with two solutions:
Move my request payload to query params.
Move my request payload to url context.
I ended up using a mix and match of both.
So, basically I used request.query_params and self.context to fetch data from the request and changed my URL and request structure accordingly.

Django app treats HTTP request as HttpRequest object, not django-rest Request object

I have the following code
class UserPollPassedView(generics.UpdateAPIView):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = UsersPollUpdateSerializer
def update(self, request, *args, **kwargs):
request.data['date_passed'] = datetime.datetime.now()
request.data['passed'] = True
return super(UserPollPassedView, self).update(request, *args, **kwargs)
When I try to access this method through such curl instrument like hurl.it, I get QueryDict is immutable error, because I'm trying to modify the content of request.data, assuming that request is Django-rest's Request object, but it's not, it is actually native Django HttpRequest object. When I explicitly define Content-type: application\json in request header, it gives me another JSON parse error. When I use httpie tool, everything goes smooth and clean, though it sends the same application\json header by default. I suppose, the difference is still in headers, but I can't understand what exactly I should change.
I also tried explicitly typecast request from HttpRequest to Request by adding the following line right before accessing request.data
request = self.initialize_request(request)
but of no use, it gives same "JSON parse error - Expecting value: line 1 column 1 (char 0)" even if request is initially Request object from httpie.
Would appreciate any clue
I don't know why you think the object is not the DRF request. Since you are using a DRF view, you get a DRF request. Django's own request object doesn't even have a data attribute.
The request variable is definitely holding a DRF Request object, and not a Django HttpRequest object. You would be getting an error about data not existing on the HttpRequest if this was not the case.
The problem is that request.data is a QueryDict object when the data is submitted as form data (like through a browser), which should be close to what you would get from request.POST/request.GET/request.FILES. This is probably why you thought it was a Django HttpRequest, because this is usually an issue people see after trying to modify any of these objects.
You are trying to modify request.data which isn't recommended and should really be treated as an immutable dictionary. Usually this is a sign that you should be setting these keys somewhere else, usually on the serializer layer or by overriding perform_update as a hook), instead of modifying the incoming request data.

How to parse request in django

Hi i am making an webserver , In which I have to hit some request from html page and return the response. The URL which is generated using html is
http://192.168.2.253:8080/searchSMS/?KPImsgId=0&circle=&subId=&startDate=DD-MM-YYYY&endDate=DD-MM-YYYY&Username=ashish
but in the server side I am not able to see the request data. I am using
q = QueryDict(request.body) but it is showing <QueryDict: {}>
How to find the all the parameters coming in request.
In your case you send the data in url so access the data through request.GET as follow:
username = request.GET.get('Username')
start_date = request.GET.get('startDate')
# ... the same for all the other parameter after the `?` marque.
In fact there is a difference between request data, request.body, request.GET and request.POST:
If you are sending POST request to django function view or class based view: you access the request data in request.body or request.POST.
If you are sending POST request to Django REST Framework: you access the data in request.data. You may also find in Internet request.DATA that correct but it's deprecated in the newer version of DRF in favor of request.data.
If you send parameter in the url like in you case, you access the data form request.GET as explained above.