Getting PATCH request parameter in Django - django

Is it possible to retrieve the request parameters of a HTTP PATCH request in Django? request.method == 'PATCH' is recognised, but I struggle to retrieve the request payload. I've tried request.REQUEST.items(), but this didn't contain any data. I know I could use Django-tastypie, but in this case, I would like to avoid it (and I supposed tastypie is using some Django methods to retrieve this data anyway).
I'm using Django 1.5.1.

You can use a QueryDict class manually. This is class implemented in django and processing all text data received through http request.
Link on the docs:
https://docs.djangoproject.com/en/1.11/ref/request-response/#django.http.QueryDict
And here is an example of usage:
from django.http import QueryDict
def home_view(request):
if request.method == 'PATCH':
data = QueryDict(request.body)
print data['your_field']

As #asitm9 mentioned, using request.data works for POST, PUT and PATCH and is recommended.

Just try to use MultiPartParser when the CONTENT_TYPE is "multipart/form-data;",else QueryDict.
if request.META.get('CONTENT_TYPE', '').startswith('multipart'):
from django.http.multipartparser import MultiPartParser
query_dict, multi_value_dict = MultiPartParser(request.META, request,
request.upload_handlers).parse()
else:
from django.http import QueryDict
query_dict = QueryDict(request.body)

raw_post_data did the trick (I used it before, but forgot it existed)

Related

GET Body is not being sent with APIClient Django DRF

i want to send body data using get request in the django drf test case APITestCase
for example
data ={'hi':'bye'}
self.client.get('media_list/', {'body': data})
and in the views i can able get the body using below code
request.data.get('hi', None)
but it is not working using {'body': data} my test method but it is working fine in the postman raw type.
what is tried is(not working)
self.client.get('media_list/', data=data)
I faced this issue while writing unit test. You can solve it with this workaround.
Problem: When you request with client.get method, the method put your data to url. You can see link in the below.
https://github.com/encode/django-rest-framework/blob/master/rest_framework/test.py#L194
Solution: You should use client.generic() directly. Don't use client.get() https://github.com/encode/django-rest-framework/blob/master/rest_framework/test.py#L203
Example
import json
from rest_framework.test import APIClient
from rest_framework.test import APITestCase
class TestClass(APITestCase):
def setUp(self):
# Setup run before every test method.
pass
def test_send_json_in_body(self):
data ={'hi' : 'bye'}
resp = self.client.generic(method="GET", path="/return/data/", data=json.dumps(data), content_type='application/json')
request._request
<WSGIRequest: GET '/return/data/'>
request.data
{'hi': 'bye'}
It works :)
data` returns request body and for get api's you need to get query params
Try bellow code:
data = {'hi':'bye'}
self.client.get('media_list/', data)
request.query_params.get('hi', None)

How does interacting with the django rest api through the url work?

I get that the Django rest framework is for interacting with the Django server programmatically but one thing I still don't understand is how.what i want to do is have my client app (mobile app) send data (somehow) to the Django server in order to create/retrieve data based on variables and obviously this has to be done through the URL since there will be no direct GUI interaction with the API. (unless I'm mistaken, which I probably am) I have gone through the official documentation and followed the tutorial to the end and still don't understand how this is supposed to work.all I ask for is a quick and simple explanation because I have searched everywhere and haven't found a simple enough explanation to grasp the core concept of how this is all supposed to work.
I think what you're looking for is JSONResponse and related objects:
This will allow you to send JSON in response to a request.
from django.http import JsonResponse
def my_view_json(request):
response = JsonResponse({'foo': 'bar'})
return response
If your templates or webpages need to make a request to a view and specify different parameters, they can do so by adding POST variables (examples). These can be parsed in the view like so:
def myView(request):
my_post_var = request.POST.get('variable_name', 'default_value')
my_get_var = request.GET.get('variable_name', 'default_value')
You can then parse what was sent any way you like and decide what you want to do with it.
Basically,
You define the URLS upon which you perform Get/POST/PUT Requests and You can Send Data to that.
Eg:
urls.py
from django.conf.urls import url,include
from app import views
urlpatterns = [
url(r'^(?i)customertype/$',views.CustomerViewSet.as_view()),
url(r'^(?i)profile/$', views.Save_Customer_Profile.as_view()),
url(r'^(?i)customer_image/$', views.Save_Customer_Image.as_view()),
]
Now Whenever User would send a Request to:
example.com/profile ==> This would be received in the Save_Customer_Profile View based on the Method Type, Save_Customer_Profile is as follows:
class Save_Customer_Profile(APIView):
"""Saves and Updates User Profile!"""
def get(self, request, format=None):
return AllImports.Response({"Request":"Method Type is GET Request"})
def post(self, request, format=None):
return AllImports.Response({"Request":"Method Type is Post Request"})
def put(self,request, format=None):
return AllImports.Response({"Request":"Method Type is Put Request"})
I think the OP was referring to how to do GET/POST request programmatically. In that case, it is enough to do (values are dummy):
GET:
import requests
r = requests.get('http://localhost:8000/snippets/')
print(r.json())
print(r.status_code, r.reason)
POST:
data = {'code': 'print(" HELLO !!!")', 'language': 'java','owner': 'testuser'}
r = requests.post('http://localhost:8000/snippets/', data=data, auth=('testuser', 'test'))

Proper way to handle PUT requests Django with forms

I have a web app that allows users to edit previously submitted data.
I'm currently processing PUT requests by manually updating the data.
I would like to use my forms to validate input but I run into the issue of the other required fields.
For instance, if a user updates a date field and I validate it with my form, it errors out as I'm missing other required fields like name, location, etc since the form was designed to be filled out all at once.
What is the best way to use my forms to validate input but conditionally allow required fields if the request is a PUT or POST with model Forms.
If you're getting errors for missing fields you're not using the modelform correctly, sounds like you are not passing it the existing instance to work on.
You need to use a pattern like this:
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render
def my_view(request, obj_id):
my_object = get_object_or_404(MyModel, pk=obj_id)
update_form = MyModelForm(instance=my_object, data=request.PUT or None)
if update_form.is_valid():
return HttpResponse(status=204) # empty success response
else:
return render(...) # render update_form.errors somehow
And be sure to include the object id in the url that you send your PUT requests to

HTTP post request in Django

I am trying to do the following:
1) A payment solution is supposed to send an HTTP Post to my site
2) I would like to read the contents of the request(xml) and update my records to reflect the payment
I am trying this for the first time. When I create a URL path, and send a post to that address I get the csrf error.
Is there a way using Django wherein I can accept a post and don't have to return a response.
Thanks
Tanmay
Your view should return an http response, otherwise you will get an error. However, Django does not mind if that response does not contain any content. Your view can be as simple as:
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def my_view(request):
# do something with request.POST
return HttpResponse("")
Since it is a third party that is submitting the post request, and not a user submitting a form on your site, you can mark the view as exempt from CSRF protection using the csrf_exempt decorator, as above.
Note that anyone could submit a post request to your url, so you should have some way of checking that the response is genuine. Your payment solution should be able to advise a suitable way to do this.

django to return json format data to prototype ajax

is there a way i can pass json format data through django HttpResponse. I am trying to call the view through prototype ajax and return json format data.
Thanks
You could do something like this inside your app views.py
import json
def ajax_handler(req, your_parameter):
json_response = json.dumps(convert_data_to_json)
return HttpResponse(json_response,mimetype='application/json')
Building on Lombo's answer, you might want to utilize the request.is_ajax() method. This checks the HTTP_X_REQUESTED_WITH header is XmlHttpRequest.
This is a good way to avoid sending a json response to a regular GET - which I guess at worst is just confusing to your users, but also lets you use the same view for ajax vs. non-ajax requests. This approach makes it easier to build apps that degrade gracefully.
For example:
def your_view(request):
data_dict = # get some data
if request.is_ajax():
# return json data for ajax request
return HttpResponse(json.dumps(data_dict),mimetype='application/json')
# return a new page otherwise
return render_to_response("your_template.html", data_dict)
This approach works particularly well for form processing also.