I am sending a POST request to my server which is throwing a 500 error when my server code attempts to read data from the POST request. But the data looks perfectly ok to me.
The POST data is:
<QueryDict: {u'{"firstname":"jack","lastname":"rowley","username":"jack","email":"info#mybiz.co.uk","password":"jack","city":"London","country":"UK","photo":"","genre1":"Comedy","genre2":"Horror","genre3":"Documentary","platform":"Cinema"}': [u'']}>
The Python code that is reading the POST data is:
username = request.POST['username']
password = request.POST['password']
email = request.POST['email']
It falls over at the first line, trying to access the username.
The AngularJS code that makes the POST request looks like this:
url = apiDomain + '/profile/register/';
var fn = 'jack';
var ln = 'rowley';
var un = 'jack';
var pw = 'jack';
var cf = 'jack';
var em = 'info#mybiz.co.uk';
var lc = 'London';
var ct = 'UK';
var ph = ''; //$('#photo_set').val();
var genre1 = 'Comedy';
var genre2 = 'Horror';
var genre3 = 'Documentary';
var platform = 'Cinema';
return $http({
method: 'POST',
url: url,
headers: {
'Content-Type': "application/x-www-form-urlencoded"
},
data: {
firstname: fn,
lastname: ln,
username: un,
email: em,
password: pw,
city: lc,
country: ct,
photo: ph,
genre1: genre1,
genre2: genre2,
genre3: genre3,
platform: platform
}
}).then(function successCallback(response) {
return response;
}, function errorCallback(response) {
return -1;
});
You are trying to access this data as if it were form-encoded. It is not; it is JSON.
You need to access the raw post body, and decode it from JSON.
data = json.loads(request.body)
username = data['username']
password = data['password']
email = data['email']
You're getting a KeyError because you don't have a username.
Your query dict is not a dict. It's a single-item string key, with an empty-string value. The key happens to be a string-encoding of some url encoding string. Look at it.
QueryDict: { u'{"fi text text text': u'' }
You are passing a URL-encoded string where you should be passing a dict, probably in the client.
Related
I made a python api that I'm trying to get my app to connect to, but for the login function I need to send the username and password but I'm not sure how to do this. This is the python code:
username = data.get('username')
email = data.get('email')
password = data.get('password')
And the Kotlin Code:
private fun sendData(username:String, password:String): Thread {
return Thread {
val url = URL("https://127.0.0.1:5000/login")
val connection = url.openConnection() as HttpsURLConnection
connection.setRequestProperty("username", username)
connection.setRequestProperty("password", password)
if (connection.responseCode == 200) {
val inputSystem = connection.inputStream
println(inputSystem.toString())
Toast.makeText(applicationContext, "It worked", Toast.LENGTH_SHORT).show()
}
else {
var code: String = "ERROR"
Toast.makeText(applicationContext, "NO CONNECTION", Toast.LENGTH_SHORT).show()
}
}
}
The connection is opened but I can get any data across and I haven't tried anything so far as I can't find good documentation on this.
You could, for example, first set up a class to handle your credentials:
class LoginData(
val userID: String,
val pw: String
){
/** Returns a hashmap of the data stored in the class object. */
fun getHashmap(): Map<String,String> {
val params = HashMap<String,String>()
params["username"] = userID
params["password"] = pw
return params
}
/** Obtains a JSONObject of the data stored in the class object. */
fun getJson(): JSONObject {
val params = this.getHashmap()
return JSONObject(params)
}
}
And then, utilising Volley (don't forget to add it to your build gradle: implementation 'com.android.volley:volley:1.2.0'), do something like this:
fun sendData(username: String?, password: String?) {
val url = "https://127.0.0.1:5000/login"
var loginData = LoginData(
userID = username!!,
pw = password!!
)
val queue = Volley.newRequestQueue(this)
val jsonRequest = JsonObjectRequest(
Request.Method.POST,
url,
loginData.getJson(),
Response.Listener {
response -> handleResponse(response)//do something with the response
},
Response.ErrorListener { error -> println("That didn't work: $error")})
queue.add(jsonRequest)
}
with handleResponse() containing your logic to evaluate what comes back from the server:
fun handleResponse(response: JSONObject) {
//your evaluation logic
}
We managed to connect to our dynamics 365 cloud instance with token auth. However, we were hoping to find package like "pydynamics".
The package "https://libraries.io/pypi/dynamics365crm-python" seems newer, but it seems only to be able to handle standard objects, not custom objects.
Our current solution works with REST only.
import requests
import json
#set these values to retrieve the oauth token
crmorg = 'https://org.crm4.dynamics.com' #base url for crm org
clientid = '<id>' #application client id
client_secret = '<secret>'
username = 'dynamics-api#org.com' #username
userpassword = 'pw' #password
tokenendpoint = 'https://login.microsoftonline.com/bb23defa-be1d-4137-969b-324f8468f15a/oauth2/token' #oauth token endpoint
authorizationendpoint = 'https://login.microsoftonline.com/bb23defa-be1d-4137-969b-324f8468f15a/oauth2/authorize'
#build the authorization token request
tokenpost = {
'client_id':clientid,
'resource':crmorg,
'client_secret':client_secret,
'username':username,
'password':userpassword,
'grant_type':'password',
'oauthUrl':authorizationendpoint
}
#make the token request
tokenres = requests.post(tokenendpoint, data=tokenpost)
#set accesstoken variable to empty string
accesstoken = ''
#extract the access token
try:
accesstoken = tokenres.json()['access_token']
except(KeyError):
#handle any missing key errors
print('Could not get access token')
#set these values to query your crm data
crmwebapi = 'https://<org>.crm4.dynamics.com/api/data/v9.1' #full path to web api endpoint
crmwebapiquery = '/new_households' #web api query (include leading /)
#prepare the crm request headers
crmrequestheaders = {
'Authorization': 'Bearer ' + accesstoken,
'OData-MaxVersion': '4.0',
'OData-Version': '4.0',
'Accept': 'application/json',
'Content-Type': 'application/json; charset=utf-8',
'Prefer': 'odata.maxpagesize=500',
'Prefer': 'odata.include-annotations=OData.Community.Display.V1.FormattedValue'
}
#make the crm request
crmres = requests.get(crmwebapi+crmwebapiquery, headers=crmrequestheaders)
try:
#get the response json
crmresults = crmres.json()['value'][0]
#loop through it
for key,value in crmresults.items():
print (key, value)
except KeyError:
#handle any missing key errors
print('Could not parse CRM results')
Anyone know a package?
REST API is the way to go.
We use them every time with JavaScript and parase the response as Json.
Below is sample call which I perform within crm, you will see the response been transformed into Json
Don't worry much about details, for you important is this line var results = JSON.parse(this.response);
var req = new XMLHttpRequest();
req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v9.1/accounts?$select=accountcategorycode,accountclassificationcode,accountid,accountnumber,accountratingcode", false);
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("Prefer", "odata.include-annotations=\"*\",odata.maxpagesize=10");
req.onreadystatechange = function() {
if (this.readyState === 4) {
req.onreadystatechange = null;
if (this.status === 200) {
var results = JSON.parse(this.response);
for (var i = 0; i < results.value.length; i++) {
var accountcategorycode = results.value[i]["accountcategorycode"];
var accountcategorycode_formatted = results.value[i]["accountcategorycode#OData.Community.Display.V1.FormattedValue"];
var accountclassificationcode = results.value[i]["accountclassificationcode"];
var accountclassificationcode_formatted = results.value[i]["accountclassificationcode#OData.Community.Display.V1.FormattedValue"];
var accountid = results.value[i]["accountid"];
var accountnumber = results.value[i]["accountnumber"];
var accountratingcode = results.value[i]["accountratingcode"];
var accountratingcode_formatted = results.value[i]["accountratingcode#OData.Community.Display.V1.FormattedValue"];
}
} else {
Xrm.Utility.alertDialog(this.statusText);
}
}
};
req.send();
I am making a POST request to send a JSON object with keys containing files. An example of what I send to the backend is:
export interface PosInputFiles {
org: string;
year_month: string;
in_master_file: File;
iv_file?: File;
sales_file?: File;
recv_file?: File;
transfer_file?: File;
adjust_file?: File;
pcount_file?: File;
gift_file?: File;
xrate?: string;
}
My POST request looks like:
generateMaster(args: PosInputFiles) {
return this.http.post('http://localhost:5000/api', args, { headers: this.headers});
}
When I try to access these files from request.json, the values are an empty dict ({}).
try:
org = request.json['org']
year_month = request.json['year_month']
in_master_file = request.json['in_master_file']
iv_file = None if 'iv_file' not in request.json else request.json['iv_file']
sales_file = None if 'sales_file' not in request.json else request.json['sales_file']
recv_file = None if 'recv_file' not in request.json else request.json['recv_file']
transfer_file = None if 'transfer_file' not in request.json else request.json['transfer_file']
adjust_file = None if 'adjust_file' not in request.json else request.json['adjust_file']
pcount_file = None if 'pcount_file' not in request.json else request.json['pcount_file']
gift_file = None if 'gift_file' not in request.json else request.json['gift_file']
xrate = None if 'xrate' not in request.json else request.json['xrate']
except:
return { "post" : "failed" }
print(in_master_file)
print(len(request.files))
return { "post": "success"}
Then I tried sending only one file and made sure len(request.json) == 0 through POSTMan and my frontend (Angular8). However, len(request.files) is also 0 and every time I try to access something, there is 400 error. My POST request is successful as I always print {"post", "success"} but for some reason, no files make it to the backend. All my files sent are real files and I have made sure that I am sending the file. Thank you so much for your help!
For those who might have the same problem eventually, here's how I solved this issue. Flask doesn't recognize files that aren't of FormData type so that's why I could only access JSON. Thus, I had to append all my files to a FormData variable.
generateMaster(submittedFiles: PosInputFiles) {
const formData: FormData = new FormData();
Object.keys(submittedFiles).forEach(key => {
if (submittedFiles[key] instanceof File) {
formData.append(key, submittedFiles[key], submittedFiles[key].name);
} else {
formData.append(key, new File([], submittedFiles[key]), submittedFiles[key].name);
}
})
return this.http.post('http://localhost:5000/api', formData, { headers: this.headers});
}
Then backend will finally recognize the files. In order to get other string data, and floats, I stored those values as the filename and could access them as such.
def post(self):
# Initilize arguments
org = request.files.get('org').filename
year_month = request.files.get('year_month').filename
in_master_file = request.files.get('in_master_file')
iv_file = request.files.get('iv_file')
sales_file = request.files.get('sales_file')
...
xrate = None if 'xrate' not in request.files else float(request.files.get('xrate').filename)
I'm getting an uncaught syntax error: unexpected string the chrome console when running ajax where I am trying to add a row to the bottom of a html table with the saved data returned with json. I really can't spot it....
function create_person() {
console.log("create person is working!")
$.ajax({
url : "{% url 'tande:create_person' %}",
type: "POST",
data: { first_name : $('#person-first-name').val(), surname : $('#person-surname').val(), email : $('#person-email').val(), coach_id : $('#person-coach-id').val(), is_coach : $('#person-is-coach').val(), position : $('#person-position').val(), contract_type : $('#person-contract').val()},
success : function(json) {
$('#person-first-name').val('');
$('#person-surname').val('');
$('#person-email').val('');
$('#person-coach-id').val('');
$('#person-is-coach').val('');
$('#person-position').val('');
$('#person-contract').val('');
console.log(json);
// ERROR OCCURS ON FOLLOWING LINE
var html = '<tr><td>'+json.personid+'</td><td>'+json.personfirstname+' '+json.personsurname'</td><td>'+json.personposition+'</td><td>'+json.personcontract+'</td><td>'+json.personemail+'</td><td>'+json.personcoachid+'</td></tr>';
console.log("success");
$('div#talk').html(html);
console.log(html)
},
error : function(xhr,errmsg,err) {
// $('#results').html("<div class='alert-box alert radius' data-alert>Oops! We have encountered an error: "+errmsg+
// " <a href='#' class='close'>×</a></div>"); // add the error to the dom
console.log("uh oh");
}
});
};
The data is saved successfully and the json object is returned to the console, I just can't display it.
def create_person(request):
if request.method == "POST":
print "request post data in view"
firstname = request.POST.get('first_name')
print firstname
lastname = request.POST.get('surname')
emailadd = request.POST.get('email')
coachid = request.POST.get('coach_id')
isacoach = request.POST.get('is_coach')
positionheld = request.POST.get('position')
contracttype = request.POST.get('contract_type')
response_data = {}
starfruit = Person(first_name=firstname, surname=lastname, email=emailadd, coach_id=coachid, assign_as_coach=isacoach, position=positionheld, contract_type=contracttype)
starfruit.save()
response_data['personfirstname'] = starfruit.first_name
response_data['personsurname'] = starfruit.surname
response_data['personemail'] = starfruit.email
response_data['personcoachid'] = starfruit.coach_id
response_data['personiscoach'] = starfruit.assign_as_coach
response_data['personposition'] = starfruit.position
response_data['personcontract'] = starfruit.contract_type
response_data['personid'] = starfruit.id
# response_data = {
# ''
# }
print response_data
return JsonResponse(response_data)
else:
print "no post request in view"
return JsonResponse(response_data)
The error I'm getting in the console is just as follows:
(index):845 Uncaught SyntaxError: Unexpected string
and it refers to the line I've highlighted above
var html = '<tr><td>'+json.personid+'</td><td>'+json.personfirstname+' '+json.personsurname'</td><td>'+json.personposition+'</td><td>'+json.personcontract+'</td><td>'+json.personemail+'</td><td>'+json.personcoachid+'</td></tr>';
I'm unsure how else to approach this...
You're missing a + between json.personsurname and the following '</td><td>'.
Generally it's a really bad idea to build up HTML like that; this sort of thing is easy to miss.
I'm trying to build a page where when the user presses a button a variable which initially is 0 increments with 1. This number is then sent asynchronously to the server by using jQuery AJAX.
What I have so far is:
In my __init__.py file:
def main(global_config, **settings):
engine = engine_from_config(settings, 'sqlalchemy.')
DBSession.configure(bind = engine)
Base.metadata.bind = engine
config = Configurator(settings = settings)
config.include('pyramid_jinja2')
config.add_static_view('static', 'static')
config.add_static_view('scripts', 'scripts')
# Removed the other views
config.add_route("declare_usage", '/user/{user_id}/{address_id}/declare')
config.add_route("declare_usage_json",'/user/{user_id}/{address_id}/declare.json')
config.scan()
My HTML + Jinja2:
#Removed code for simplicity
<div id="button_add">Add</div>
{{val}}
My JS:
$(document).ready(function(){
var room = 0;
jQuery.ajax({type:'POST',
url: '/user/1/5/declare', #I use a direct user ID and a direct address ID as I'm not sure how to send this to JS from Pyramid ... yet :).
data: JSON.stringify(room),
contentType: 'application/json; charset=utf-8'});
$('#button_add').click(function(){
room = room + 1;
});
});
My view code:
#view_config(route_name = 'declare_usage', renderer = 'declara.jinja2')
#view_config(route_name = 'declare_usage_json', renderer = 'json')
def declara_consum(request):
#Removed code for simplicity
val = request.POST.get('room') #I get a "None value in my html" if I change to request.json_body -> I get an error that there is no json to be parsed.
return { 'val' : val }
What happens is that when I open the debugger the POST request is successful with no data and on the page I get 2 options for 'val':
None -> When I use val = request.POST.get('room')
Error ValueError: No JSON object could be decoded -> When I use val = request.json_body
Also, still can't get it to work if in my JS i change url to be /user/1/5/declare.json and/or data to {'room' : room}
Can somebody please point out what I'm doing wrong?
you don't need another route declare_usage_json, just need separate two function like this
#view_config(route_name = 'declare_usage', renderer = 'declara.jinja2')
def declara_consum(request):
# this will response to your jinja2
return { 'val' : val }
#view_config(route_name = 'declare_usage', xhr=True, renderer = 'json')
def declara_consum_ajax(request):
# this will response to your asynchronously request
val = request.POST.get('room')
return { 'val' : val }
when you send a request using ajax, this will goto the second function.
$.ajax({
type: 'POST',
url: '/user/1/5/declare',
data: {'room' : room},
dataType: 'json'
}).done(function(response){
// update your data at html
});