Access raw_post_data in django test client - django

The title pretty much says it all: I use raw_post_data in a couple of views, and thus I need the test client to properly grant access to it.
I have copied the raw_post_data string, from a mock request, passed it to json.loads(), and then used the resulting dict as the POST data for the test client. Then, I set the content type to "application/json" - this causes raw_post_data to appear, but it is not the same raw_post_data as the mock request.

When you change the content type in the test client, the data parameter is not parsed as a dictionary anymore but sent directly. Try copyin your JSON string directly as the data parameter to your post request, you should receive it in raw_post_data in your application.

Just need to follow the steps as below:
1. set the data attribute to your string.
2. then set the content_type attribute to application/octet-stream.
payload = {'k1':'v1'}
data = json.dumps(payload)
response = self.client.post(url, data=data, content_type='application/octet-stream', **self.auth_headers)

Related

Pass dynamic value to url in Postman

I have 2 requests
1st Request
After did my first request, I get the response where I can parse for a taskId
In my test tab, I will then parse and store it like this
let taskId = pm.response.json().body.result[0].data.task
console.log(taskId)
I can see taskId printing in my console as 938
2nd Request
I require making a GET with this dynamic URL with the taskId that I got from the first one
http://localhost:3000/fortinet/monitor/{{taskId}}
So I set the above URL , set the HTTP verb to GET
in my Pre-request Script tab, I did this
let taskId = pm.globals.get("taskId")
Result
ReferenceError: taskId is not defined
Image Result
How can I debug this further?
The most suggested way is to use :key as in
http://localhost:3000/fortinet/monitor/:taskId
See the colon before taskId. The reason being, URI values sometimes many not be environment dependent. So, based on the usecase, you can use like I said or {{taskId}}
You have to set variable, but you are doing it wrong.
try this:
pm.globals.set("taskID", pm.response.json().body.result[0].data.task)
more you can read here:
https://learning.postman.com/docs/postman/variables-and-environments/variables/
Please note, that URL which ends with resource identified like https://example.com/:pathVariable.xml or https://example.com/:pathVariable.json will not work.
You can go with https://example.com/:pathVariable with Accept: application/json header.
For passing dynamic value, first you have to set it in environment or global variable in Tests tab because tests runs after request and you will get response value after request sent, but because you get response in json you have to first parse it, so what you can write in Tests tab is as follows:
var jsonData = JSON.parse(responseBody);
postman.setEnvironmentVariable("taskId", jsonData.token); // OR
postman.setGlobalVariable("taskId", jsonData.token);
Then you can use taskId as {{taskId}} wherever you want in url parameters or in request body or form data wherever.
If you want to know in detail how to extract data from response and chain it to request then you can go to this postman's official blog post which is written by Abhinav Asthana CEO and Co Founder of Postman Company.

Using postman to test POST request, how do I access the form-data inside the request?

I've been googling for a few hours, and I need help. I dont think I'm using the correct words. Anyhow, I'm using Claudia.JS to set up a POST request to my AWS Lambda function. Here's the basics of the function:
api.post('/leads', function (request) {
console.log(request);
return request;
});
When I use postman to test the post request, I'm returned the request object. Awesome. Then I try to pass form-data through. I set the key to 'username' and the value to 'this is the username'. This is what request.body is:
"body": "---------------------------
-019178618034620042564575\r\nContent-Disposition: form-data;
name=\"username\"\r\n\r\nthis is the username\r\n----------------------
------019178618034620042564575--\r\n",`
I thought I could return request.body.username... to key the value of username...but I'm missing something.
How do I access the form data in the request?
update: okay. The website is taking the form data, making a post request...this function is receiving the post request? still-- in postman...if I were to put my own JSON in...why can I not access request.body like... request.body.username?
You should try console.log(request.data) to see your request object, ie. in my own case I can see the content of my request's body.
Have a look at https://www.getpostman.com/docs/postman/scripts/postman_sandbox to see all the relevant information about your request.
I solved this by looking at the header set in postman. It was set to form-data instead of application/JSON. All gravy now.

Missing form data in request

I have following code
class MyClass(restful.Resource):
def get(self):
headers = {'Content-Type': 'text/html'}
return make_response(render_template('myfile.html'),200,headers)
def post(self):
session['CONSUMER_KEY']=request.form.get('consumer_key')
session['CONSUMER_SECRET']=request.form.get('consumer_secret')
render_template('myfile.html')
api.add_resource(MyClass,"/mag/",endpoint="mag")
I have written following test:
def mytest(self):
content_type={"Content-Type": "application / x - www - form - urlencoded","Content-Disposition": "form-data"}
response = self.client.post(
api.url_for(MyClass), data = json.dumps({'consumer_key':'testconsumerkey',
'consumer_secret':'testconsumersecret'}),
headers=content_type
)
The issue is form data is blank and thats the values are not getting set in session. When i debug i see that request.data is populated but request.form is an empty dictionary. Can someone suggest how I can send form data in a post request from a test
EDIT: Environment details
Python 2.7, Flask web framework, self.client is . I am using flask.ext.testing
You seem to be confused as to what the expected format for the post body should be. Should it be JSON data (which is what you send in the test case), or should it be in the application/x-www-form-urlencoded format (which is what you claim to send in the test case, and what the endpoint will read)?
If you wish to receive JSON data, you'll need to change the endpoint to read the data from request.get_json(). You'll also need to use application/json as the Content-Type header in the test case.
If you wish to receive urlencoded post data, then just simplify the test case by removing the Content-Type header and the json.dumps. Just pass the data dict to the data argument.

How to use Backbone collection's create method correctly

I found that when I use the collection.create to create a new model, backbone will send a post request, but the post data is incorrect
for example
collection.create({name:'test'})
backbone will send POST data using "{name:'test'}" as key, and "" as value,
but I want the POST data by using name as key, 'test' as value,
can anybody no how to setting it,
I use django as the server
thanks in advance
Unless you change it backbone's collections use Backbone.sync to communicate with your backend.
In the docs they say:
With the default implementation, when Backbone.sync sends up a
request to save a model, its attributes will be passed, serialized as
JSON, and sent in the HTTP body with content-type application/json
So I guess you need to do something like this in your django view
json.load(request.POST)
or use a custom sync function that does not serialize the data to json
You'll need to parse the raw post data string and parse it into a python dict.
import json
data = json.loads(request.raw_post_data)
You can also set
Backbone.emulateJSON = true;
as per http://backbonejs.org/#Sync-emulateJSON

How to send data as key - value pairs instead of string via POST using XHR

I'm creating two POST calls. One using a django form and one using angular js via a resource xhr.
The angular setup looks like this:
myModule.factory('gridData', function($resource) {
//define resource class
var root = {{ root.pk }};
var csrf = '{{ csrf_token }}';
return $resource('{% url getJSON4SlickGrid root.pk %}:wpID/', {wpID:'#id'},{
get: {method:'GET', params:{}, isArray:true},
update:{method:'POST', headers: {'X-CSRFToken' : csrf }}
});
});
With creating an xhr post request as such:
item.$update();
This post request is send to the server as expected, but when I want to access the QueryDict I cannot access the data passed using:
name = request.POST.get('name', None)
name is always None like this.
The issue behind this is that the QueryDict object is getting parsed quite strange.
print request.POST
<QueryDict: {u'{"name":"name update","schedule":0"}':[u'']}>
Whereas I would have expected this result, which I got when I send the data via a "normal" Post request:
<QueryDict: {u'name': [u'name update'], u'schedule': [u'0']}>
So it seems to be that Django receives something in the POST request which instructs Django to parse the parameters into one string. Any idea how to circumvent this?
Update:
I found this discussion where they say that the issue is if you provide any content type other than MULTIPART_CONTENT the parameters will be parsed into one string. I checked the content-type send with the POST request and it is really set to 'CONTENT_TYPE': 'application/json;charset=UTF-8'. Thus this is likely the issue. Therefore my question is: How can I set the CONTENT_TYPE for a xhr post request created using angular.js resources to MULTIPART_CONTENT?
you could either:
fiddle with the client to send data instead of json
use json.loads(request.raw_post_data).get('name', None) (django < 1.4)
use json.loads(request.body).get('name', None) (django >= 1.4)
The Angular documentation talks about transforming requests and responses
To override these transformation locally, specify transform functions as transformRequest and/or transformResponse properties of the config object. To globally override the default transforms, override the $httpProvider.defaults.transformRequest and $httpProvider.defaults.transformResponse properties of the $httpProvider.
you can find an example here as was previously pointed at.