I am using django v2.2.4 and need to access request body data.
Here's my code:
#api_view(['POST'])
#renderer_classes((JSONRenderer,))
def index(request):
if request.method == 'POST':
results= []
data = JSONParser().parse(request)
serializer = ScrapeSerializer(data=data)
if serializer.is_valid():
url = request.data.url
#url = request.POST.get('url')
But I get this error:
RawPostDataException at /scrape/
You cannot access body after reading from request's data stream
Here's the request body:
{
"url": "xyz.com"
}
How can I access the request body?
I have found this SO post that related to this issue, Exception: You cannot access body after reading from request's data stream
Anyway use request.data instead of request.body in DRF
#api_view(['POST'])
#renderer_classes((JSONRenderer,))
def index(request):
if request.method == 'POST':
results = []
serializer = ScrapeSerializer(data=request.data)
if serializer.is_valid():
url = request.data["url"]
The request.data returns the parsed content of the request body and it will be dict like object, hence the dot operation (request.data.url) won't works here.
To access the request body of a POST request, you could do this by url = request.POST.get("url")
Related
I want my page to reload and show the django messages sent to the page when a POST call is made (by another user).
From api I am calling the method like that:
def create(self, request, pk=None):
json_data = json.loads(request.body)
sample_path = json_data['sample_path']
try:
sample = BloodSample.objects.get(sample_path = sample_path)
if json_data['status'] == 201:
BloodSampleAdmin(sample, BloodSample).display_messages(request, sample)
return Response(json_data['body'], status = status.HTTP_201_CREATED)
and the method in BloodSampleAdmin is:
def display_messages(self, request, sample):
messages.success(request, ("hurray"))
return HttpResponseRedirect(reverse(
"admin:backend_bloodsample_change",
args=[sample.id]
))
I am 100% sure that the method is called (debug). But message wont pop anyway.
I am using Postman to send the POST request.
Any ideas on what is going wrong?
This question already has answers here:
#csrf_exempt does not work on generic view based class
(4 answers)
Closed 3 years ago.
I wrote a test file to check if the URL works or not and it keeps printing Forbidden (CSRF cookie not set.) could please check what's the problem
#post handler
#csrf_exempt
def post(self, request, *args, **kwargs):
valid_json = is_json(request.body)
if not valid_json:
error_data = json.dumps({'message': 'Invalid data sent, please send using JSON format'})
return self.render_to_response(error_data, status=400)
data = json.loads(request.body)
form = SupervisorForm(data)
if form.is_valid():
obj = form.save(commit=True)
obj_data = obj.serialize()
return self.render_to_response(obj_data, status=201)
if form.errors:
data_error = json.dumps(form.errors)
return self.render_to_response(data_error, status=400)
json_data = json.dumps({'message': 'Not Allowed'})
status_code = HTTP_400_BAD_REQUEST
return self.render_to_response(json_data, status_code)
def post():
data = {
'supervisor_name':'name',
'supervisor_phone': '76786875',
'supervisor_email': 'sdsds#sdsd.com',
'supervisor_image': 'path to local image',
}
json_data = json.dumps(data)
json_loads = json.loads(json_data)
print(type(json_data))
print(type(json_loads))
print(help(requests.put))
r = requests.put('http://127.0.0.1:8000/api', json = json.dumps(data))
return r.json()
You have probably configured your Django to use a CSRF token but have not set it up for your API. Are you able to disable CSRF in your configuration? Otherwise, you'd have to set it up in accordance with the documentation
CSRF is important for websites that are at a high risk of getting hacked through scripts/iframes. CSRF is what prevents your bank account from sending money to a hacker via email/popup scripts. Unless you're building a website that has confidential data scoped to the user (e.g. Facebook, Venmo, PayPal) CSRF is not necessary.
I have one view which has POST and GET request. For POST request data comes from other URL. I don't use this view to POST the data. However, I have a GET request for the same view which retrieves data from the model and displays it. Now, when I open (GET request) this view it correctly shows the data. But in addition it shows text area for a POST request as well. I want to hide POST request on my view.
Code:
#api_view(['POST','GET',])
def TestView(request):
if request.method == 'POST':
data = json.loads(request.body.decode('utf-8'))
customers_instance = Customers.objects.create(firstname=data[0]["value"],
lastname=data[1]["value"],
dob=data[2]["value"],
emailaddress=data[3]["value"],
address1=data[4]["value"],
address2=data[5]["value"],
city=data[6]["value"],
state=data[7]["value"],
postalcode=data[8]["value"])
return HttpResponse('Data has been received by API')
if request.method == 'GET':
qs= Customers.objects.values('emailaddress','customer_id')
serializer_class = CustomersKeySerializer
return Response(serializer_class(many=True).to_representation(qs))
Jay,
I think you should use two different views since you are dealing with two different URL's: one for GET and one for POST request.
#api_view(['GET',])
def TestGetView(request):
if request.method == 'GET':
qs= Customers.objects.values('emailaddress','customer_id')
serializer_class = CustomersKeySerializer
return Response(serializer_class(many=True).to_representation(qs))
#api_view(['POST',])
def TestPostView(request):
if request.method == 'POST':
data = json.loads(request.body.decode('utf-8'))
customers_instance = Customers.objects.create(firstname=data[0]["value"],
lastname=data[1]["value"],
dob=data[2]["value"],
emailaddress=data[3]["value"],
address1=data[4]["value"],
address2=data[5]["value"],
city=data[6]["value"],
state=data[7]["value"],
postalcode=data[8]["value"])
return HttpResponse('Data has been received by API')
I want to parse incoming POST data in django views.py file
POST data:
{
"number" : "17386372",
"data" : ["banana","apple","grapes" ]
}
Here is how I tried to read above incoming data with request
views.py
class Fruits(APIView):
def post(self, request, format=None):
if request.method == "POST":
number = request.data.get('number')
fruits_data = json.loads(request.body)
if number not in [None, '', ' ']:
try:
response = {"return": "OK","data":fruits_data['data']}
return Response(response)
except:
return Response({"return": "NOT OK"})
else:
return Response({"return": "NOT OK"})
else:
return Response({"return": "NOT OK"})
ERROR:
You cannot access body after reading from request's data stream
The Django json parser does this already for you:
from rest_framework import parsers
class Fruits(APIView):
parser_classes = (parsers.JSONParser,)
def post(self, request, format=None):
number = request.data['number']
fruits = request.data['data']
If the Content-Type of your http request is already set properly to application/json you do not even need to specify the parser.
request.data and request.body are the two mechanisms, which reads the raw http request and construct data in a format, that is suitable to be used in python environment. Here the problem is that you are using both of them simultaneously. Thus, the inputstream of http connection is already read, by request.data call. Now request.body also tries to access the same stream, which doesn't contain now any data. Thus, it's throwing an error.
For you, I think following code will work :
fruits_data = json.loads(request.body)
number = fruits_data["number"]
This is my view
from rest_framework_xml.renderers import XMLRenderer
#api_view(['GET', 'PUT', 'POST'])
#renderer_classes((XMLRenderer,))
#permission_classes((AllowAny,))
def users(request, id, format=None):
serializer = MySerializer(model, context={'request': request})
return Response(serializer.data)
If i visit the URL by browser then i get XML as response in chrome as desired.
But in my tests
url = reverse('user-detail', kwargs={
'id': 10,
})
response = self.client.get(url)
result = response.data
I get the result as dictionary . I mean the result which i get before passing to XMLRender.
I don't know if thats the desired behaviour but how can test the xml response
The .data property of the Response holds the unrendered content. You want to access .content to see your rendered XML.