Django POST request from Postman - python

I am currently stuck with POST requests in Django. I am trying to send a POST request from an external applications such as smartphones or Postman (not forms) to the rest framework. Get requests work just fine.
I went through many posts but couldn't resolve my issue. I tried to use request.body but always get an empty response. I used print(response.body) to print the output to the console and only get b'' back.
class anyClass(APIView):
def post(self, request):
print(request.body)
return Response({"id": 'anyClass',
"data": '1234',
})
How would I get the data from my request?
My post request sent with Postman:
http://127.0.0.1:8000/test/v2/Api/anyClass?qrcode=100023&date=2018-11-27&time=08:00:00&value_1=17

You can get the response in request.data:
class anyClass(APIView):
def post(self, request):
print(request.data)
return Response({"id": 'anyClass',
"data": '1234',
})
Please see the documentation for details.
Update
I think you are making wrong kind of usage of postman. Please see the screen shot regarding how to use it:

Related

Enabling CSRF for Django

I have the following python code in my Django views.py, the code takes in a JSON body and send the extracted DATA to another API endpoint, I have simplified the code here.
How do I enable csrf such that it will send the token back to the caller for this method? I am calling this from postman.
#csrf_protect
def validate_booking(request):
if request.method != "POST":
return HttpResponseServerError("Invalid HTTP method")
body = json.loads(request.body)
booking_details = body["booking_details"]
DATA = {
"name": booking_details["name"],
"nric": booking_details["nric"],
"booking_id": booking_details["booking_id"]
}
return HttpResponse(status="200")
This site directs to put this piece of code in my method. But what is "a_template.html"?
https://docs.djangoproject.com/en/4.1/ref/csrf/
#csrf_protect
def my_view(request):
c = {}
# ...
return render(request, "a_template.html", c)
This isn't an easy thing to do as CSRF is 2 steps thing
There is a value that is passed to the client and it is saved to the session on the server.
When a POST request is received, the client shall send this as csrfmiddlewaretoken in the body and the server will check the value against the stored one in the server's session.
So this isn't feasible to be done in APIs as you require session Management which is not of REST API implementations.
Thanks for your reply. I managed to find a solution by doing the following:
Create a new GET method that will generate the session CSRF token using python
Instead of using render which expects a HTML template file, I used JsonResponse(data) to return in JSON format directly
In my postman app which I am making the POST request with the X-CSRFToken in the header, I will first make a GET request to the new method I created in step 1 to retrieve the token and store it as an environment variable
The following is the GET method sample:
from django.http import JsonResponse
def get_csrf_token(request):
csrf_token = csrf(request)['csrf_token']
data = {'csrf_token': csrf_token}
return JsonResponse(data)

Even if I send various methods to my django api server by postman, my django api server always receives them only as get

Even if I send it with a method other than get, my django api server always receives it as get. What's wrong with this?
class A(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
return JsonResponse({"message": "Hello, world!"})
As you can test from Postman (if you have it), you cannot use POST, so there's no need to disable something. It's already only for GET requests.
You should add "/" at the end of the postman url.
For example: http://127.0.0.1:8000/signup/

Django receiving QueryDict instead of JSON (from jQuery post)

I have a Django Rest API on back-end that stores questions and answers. I also have question sessions, it's an array of questions that has to be processed within 1 request.
The problem is, it works well when I send those requests from curl but when I do this via jquery Django receives QueryDict instead of json.
My js:
$.post('http://127.0.0.1:8000/api/sessions/create/', {
questions: JSON.stringify(questions)
})
When I log JSON.stringify(questions) I see it's looking like it has to be:
[{"description":"test5","type":"YESNO","to_close":5,"choices":""},{"description":"test5","type":"YESNO","to_close":5,"choices":""}]
I can even copy and paste it to curl, and it will work:
curl -X POST http://127.0.0.1:8000/api/sessions/create/ -H 'Content-Type: application/json' --data '{"questions":[{"description":"test4","type":"YESNO","to_close":5,"choices":""},{"description":"test3","type":"YESNO","to_close":5,"choices":""}]}'
But when I do via JS, Django receives it this way:
<QueryDict: {'questions': ['[{"description":"test5","type":"YESNO","to_close":5,"choices":""},{"description":"test7","type":"YESNO","to_close":5,"choices":""}]']}>
My post method looks like this:
def post(self, request, **kwargs):
"""Create a session of questions"""
question_data = request.data.pop('questions')
session = QuestionSession.objects.create()
for question in question_data:
Question.objects.create(
description=question['description'],
question_type=question['type'],
answers_to_close=question['to_close'],
question_session=session)
serializer = QuestionSessionSerializer(data=request.data, many=True)
serializer.is_valid()
serializer.save()
return Response({
'status': 'SUCCESS',
'message': 'A new session has been created!'
})
What is wrong? Since I can easily do it via curl, I think the problem is in jquery request.
I was having this exact same issue and what has worked for me was adding , content_type="application/json" inside my post.

Flask coverting to and from JSON

I'm working on a Flask example that takes blog posts and adding them to a database through a RESTful service.
Prior to implementing the RESTful service, I was adding blog posts to a local database by doing the following:
#main.route('/', methods=['GET', 'POST'])
def index():
form = PostForm()
if current_user.can(Permission.WRITE_ARTICLES) and \
form.validate_on_submit():
post = Post(body=form.body.data,
author=current_user._get_current_object())
db.session.add(post)
return redirect(url_for('.index'))
Now that I've gotten to the RESTful service section, the following to_json() and from_json() functions have been to the Post model:
//Convert a post from JSON
//Class Post(db.Model)
def to_json(self):
json_post = {
'url': url_for('api.get_post', id=self.id, _external=True),
'body': self.body,
'body_html': self.body_html,
'timestamp': self.timestamp,
'author': url_for('api.get_user', id=self.author_id,
_external=True),
'comments': url_for('api_get_post_comments', id=self.id,
_external=True),
'comment_count': self.comments.count()
}
return json_post
//Create a blog post from JSON
//Class Post(db.Model)
#staticmethod
def from_json(json_post):
body = json_post.get('body')
if body is None or body == '':
raise ValidationError('post does not have a body')
return Post(body=body)
The following inserts a new blog post in the database:
//POST resource handler for posts
#api.route('/posts/', methods=['POST'])
#permission_required(Permission.WRITE_ARTICLES)
def new_post():
post = Post.from_json(request.json)
post.author = g.current_user
db.session.add(post)
db.session.commit()
return jsonify(post.to_json()), 201, \
{'Location': url_for('api.get_post', id=post.id, _external=True)}
Would really appreciate it if someone could explain how these functions work with each other. My understanding of it all is that a blog post is typed up on a client device and in order to send it to the web service, the to_json function is called to convert the post to JSON. Once the web service receives the JSON version of the blog post, the from_json function is called to convert the JSON post back to its original state. Is that correct?
Edit:
Just re-read the page and I think my understanding was reverse of whats actually happening. In order to get a blog post from the web service, the to_json function is called to convert the data to JSON. Then on the client side, the from_json function is called to convert the data back from JSON.
Your edit is correct. A common response format for a REST API is JSON, which is why the the response is converted "to JSON" when returning.
Also a common header for sending data to a REST API is application/json, which is why the code converts the received data "from JSON".

Flask with Angular: POST form is empty

I'm sending data via AngularJS POST request:
$http.post('/process', { 'uid': uid, 'action': action }).success(function(response) {
console.log(response);
});
And trying to get sended values in Flask
#app.route('/process', methods = ['POST'])
def process():
return json.dumps({ 'data': request.form.get('uid', 'EMPTY') })
And Flask returns back {"data": "EMPTY"} response. request.form is empty. I've tried to get data from request.data, but it's in strange format there.
I'm learning Python and Flask so I want to do this work with native library, without any other packages right now.
get_json() method helps me
#app.route('/process', methods = ['POST'])
def process():
return json.dumps({ 'data': request.get_json().get('uid') })
If you want to get the data via request.form, you need to have angular send it differently. See this question for details: How can I post data as form data instead of a request payload?
Make sure Content-Type is application/json
Here's a tutorial series on using Flask and AngularJS together - http://tutsbucket.com/tutorials/building-a-blog-using-flask-and-angularjs-part-1/
Hope you'll find it useful.

Categories