So I have been going at this for hours. Usually this works out for me so I decided to ask for some help. My Http Post from AngularJS:
$scope.receipt_pay_update = function(){
response = confirm("Do you want to continue with the changes?")
if(!response){
return;
}
var data = {
'items': "ABC",
}
console.log($scope.current_farmer)
$http.post('/foodhub/dashboard/receipt_pay_modal_update',data, {data: JSON}
)}
Here is my views.py for the request:
def receipt_pay_modal_update(request):
import sys
reload(sys)
sys.setdefaultencoding('utf8')
print "#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$"
print request
print "#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$"
print request.GET
I am trying to get that "ABC" but it keeps showing empty. Here is my logs:
#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$
<WSGIRequest: GET '/foodhub/dashboard/receipt_pay_modal_update/'>
#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$#$$$$##$$$
<QueryDict: {}>
This usually works for me so I have no idea what is happening.
EDIT: So even though I am doing a POST I keep getting GET in the request body
Related
I'm a beginner.
What I used was flask and pymongo.
If you press the button, it's "Like". It should be +1, but there is a key error at the bottom.
My python route code:
#app.route('/api/like', methods=['POST'])
def like_movie():
title_receive = request.form['title_give']
movie = db.toytoy.find_one({'title': title_receive})
current_like = movie['like']
new_like = current_like + 1
db.toytoy.update_one({'title': title_receive}, {'$set': {'like': new_like}})
return jsonify({'msg': 'like!'})
This is how I POST from JS
function like_movie(title) {
$.ajax({
type: 'POST',
url: '/api/like',
data: {title_give: title},
success: function (response) {
console.log(response)
alert(response['msg']);
window.location.reload();
}
});
}
I get an exception as below:
werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'title_give'
What I want is if it's 'like_btn'. If you press the button, it becomes +1.
The base problem in what you did is not respecting Content-type. From front JS, you are making a POST with JSON object. Which makes the request to have a content type of application/json.
In backend code, you use request.form which expects the request to be in the form encoded types (like application/x-www-form-urlencoded, multipart/form-data) etc.
So, you need to read the JSON content in backend, instead of reading from a form which is not available. Like below:
ui_req = request.get_json()
title_receive = ui_req['title_give']
And then parse other structures accordingly.
UPDATE
For me the Problem got fixed as soon as I was putting "encoding: URLEncoding(destination: .queryString)" in my request. Maybe this helps somebody else. link
I struggled the whole day to find the problem in my Alamofire PUT Request or the Flask Restful API. Request like GET, DELETE and POST are working fine with Alamofire, except the PUT Request.
When I'm using PUT Requests in combination with Postman and Flask-Restful everything is also working fine. But as soon as I'm trying to achieve the same Result with Alamofire, I'm not getting any parameters in Flask. I tried to illustrate this in the code examples.
So in short my example illustrates the following:
DELETE Request(Same with GET and POST)
Postman: success
Alamofire: success
PUT Request
Postman: success
Alamofire: failure (parameter dictionary empty in Flask-Restful)
Here is my Python Code [API Server]:
from flask import Flask, request, jsonify
from flask_restful import Resource, Api, reqparse
app = Flask(__name__)
api = Api(app)
class Stackoverflow(Resource):
def delete(self):
print(request.args)
if request.args.get('test-key') is None:
return jsonify({"message": "failure"})
else:
return jsonify({"message": "success"})
def put(self):
print(request.args)
if request.args.get('test-key') is None:
return jsonify({"message": "failure"})
else:
return jsonify({"message": "success"})
api.add_resource(Stackoverflow, '/stackoverflow')
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
If I'm using Postman, I get this result (like expected):
Result in Postman
But now I'm trying to do the same with Alamofire in Swift. Same Server, nothing changed.
SWIFT demo Code [IOS APP]:
import UIKit
import Alamofire
import SwiftyJSON
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view
simplePUTRequest()
simpleDELETERequest()
}
func simplePUTRequest(){
AF.request("http://localhost:5000/stackoverflow", method: .put, parameters: ["test-key":"testvalue"])
.validate(statusCode: 200..<300)
.responseJSON { response in
if let data = response.data {
print("Result PUT Request:")
print(String(data: data, encoding: .utf8)!)
//print(utf8Text)
}else{
}
}
}
func simpleDELETERequest(){
AF.request("http://localhost:5000/stackoverflow", method: .delete, parameters: ["test-key":"testvalue"])
.validate(statusCode: 200..<300)
.responseJSON { response in
if let data = response.data {
print("Result DELETE Request:")
print(String(data: data, encoding: .utf8)!)
//print(utf8Text)
}else{
}
}
}
Xcode Console:
Result PUT Request:
{
"message": "failure"
}
Result DELETE Request:
{
"message": "success"
}
python Console (both Alamofire Requests):
ImmutableMultiDict([])
127.0.0.1 - - [15/Jun/2019 21:17:31] "PUT /stackoverflow HTTP/1.1" 200 -
ImmutableMultiDict([('test-key', 'testvalue')])
127.0.0.1 - - [15/Jun/2019 21:17:31] "DELETE /stackoverflow?test-key=testvalue HTTP/1.1" 200 -
As you can see, I'm getting the success message only while using the DELETE method.
Till now I tried using different encodings like URLEncoding.httpbody and URLEncoding.default, but nothing really helped.
For me it seems like it's a Alamofire/Swift Problem, because in Postman the same request method is working fine.
I would really appreciate your help, because I'm stuck and don't know anything further to do. I hope I didn't misunderstood something essential.
Thank you in advance!
I am currently using the same version AlamoFire, and when I use the PUT method, I use it as follows:
let request = AF.request(url, method: .put, parameters: ["uid": uid],
encoding: JSONEncoding.default, headers: headers)
request.responseJSON(completionHandler: { response in
guard response.error == nil else {
//Handle error
}
if let json = response.value as? [String: Any]
// Handle result.
}
The only difference to your post is that I used the encoding option. You can try to put the option and see what happens.
It looks like your server is expecting your PUT parameters to be URL form encoded into the URL. You may be hitting the version of the request method that uses JSON encoding by default, so adding encoder: URLEncodedFormParameterEncoder.default at the end of your request call should fix that. A future release will make that the default, as it's safe across all request types.
If that's not the issue, I suggest you investigate more closely to see what the differences between the requests may be. Since you control the server you should have easy access to the traffic.
I am reviewing this repository https://github.com/ibrahim4529/flask-chatbot to get an inspiration and see how a model can be deployed in a chat UI. I am able to do this in Flask but ran across a quirky situation that I am not sure how to resolve. The UI accepts the first initial message that I type, but when I try returning the response, I get an 'undefined' appended to every line that is supposed to be the bot's response. On CMD though, my function is returning response. I've provided screenshots below:
Here is my routing:
#app.route('/')
def hello():
return render_template('index.html')
#app.route('/ask', methods={'POST', 'GET'})
def ask():
if request.method == 'POST':
message = (request.form['messageText'])
bresponse = response(message)
return render_template('Index.html', bresponse=bresponse)
'response' is a function that spits out the response of the model (this is the 'Rrraawwwwg!' response from the input).
Below is the js that I reviewed from the link that I am using:
$('#chatbot-form').submit(function(e) {
e.preventDefault();
var message = $('#messageText').val();
$(".media-list").append('<li class="media"><div class="media-body"><div class="media"><div style = "text-align:right; color : #2EFE2E" class="media-body">' + message + '<hr/></div></div></div></li>');
$.ajax({
type: "POST",
url: "/ask",
data: $(this).serialize(),
success: function(response) {
//console.log(response);
$('#messageText').val('');
var answers = response.answers;
const chatPanel = document.getElementById("chatPanel");
$(".media-list").append('<li class="media"><div class="media-body"><div class="media"><div style = "color : white" class="media-body">' + answers + '<hr/></div></div></div></li>');
$(".fixed-panel").stop().animate({ scrollTop: $(".fixed-panel")[0].scrollHeight}, 1000);
I am not sure what I am missing. I am seeing the response in the cli, but seeing an undefined in the UI.
Thanks in advance!
I finally was able to make this work. I've updated ajax to below:
var answers = response;
$('#messageText').val();
I was also printing the response function, instead of returning it; reason I am seeing the response in the console and not in the view. This was the main culprit.
#!/usr/bin/python
import json
import cgi
import os
print 'Content-Type: application/json'
print
response={'host':cgi.escape(os.environ["REMOTE_ADDR"])}
jsondata=json.dumps(response)
print jsondata
I am unable request url throw the following javascript/jquery code:
jquery.getJSON("http://ourdomain/cgi-bin/serverscript.py", function(data){
alert("----------");
});
When I was browsing the same url, I am getting data.
First, check that you're actually loading the jQuery library in your browser. If entering jQuery() or $() in the console returns undefined or [], then you're not loading the jQuery library in the page.
Second, the print method in your python code prints the data, but does not return it back to the calling function.
To fix this, change print to return. Also, I'd suggest changing your function to the following:
response = {'host' : cgi.escape(os.environ["REMOTE_ADDR"])}
return json.dumps(response)
Your print statements don't do anything and the entire purpose of this code snippet is to get the address of the server environment.
In fact, this can all be done in one single line:
return json.dumps( { 'host' : cgi.escape( os.environ[ "REMOTE_ADDR" ] ) } )
It is solved by using jsonp request.
In a template I have the following code.
<script>
var url="/mypjt/my_timer"
$.post(url, paramarr,
function callbackHandler(dict)
{
alert('got response back');
if (dict.flag == 2)
{
alert('1');
$.jGrowl("Data could not be saved");
}
else if(dict.ret_status == 1)
{
alert('2');
$.jGrowl("Data saved successfully");
window.location = "/mypjt/display/" + dict.rid;
}
},
"json"
);
</script>
In views I have the following code,
def my_timer(request):
dict={}
try:
a = timer.objects.get(pk=1)
dict({'flag':1})
return HttpResponse(simplejson.dumps(dict), mimetype='application/javascript')
except:
dict({'flag':1})
return HttpResponse(simplejson.dumps(dict), mimetype='application/javascript')
Since we are making a JSON request and in the try block, after setting the flag, can't we return a page directly as
return render_to_response('mypjt/display.html',context_instance=RequestContext(request,{'dict': dict}))
instead of sending the response, because on success again in the HTML page we redirect the code?
Also if there is a exception then only can we return the JSON request.
My only concern is that the interaction between client and server should be minimal.
If you do the response like you said,
return
render_to_response('mypjt/display.html',context_instance=RequestContext(request,{'dict':
dict}))
the JavaScript code will receive your response, not the navigator. I think you can do somethink like this:
<script>
$(document).ready(function()
{
$('#yourForm').submit();
});
</script>
<form id="yourForm" action="/mypjt/my_timer" method="post">
...
your fields with data, even they are hidden
...
</form>
So, in Django you can do the response like you said:
def my_timer(request):
dict={}
try:
a= timer.objects.get(pk=1)
dict({'flag':1})
return render_to_response('mypjt/display.html',context_instance=RequestContext(request,{'dict': dict}))
except:
dict({'flag':0})
return render_to_response('mypjt/error_not_found.html',context_instance=RequestContext(request,{'dict': dict}))
Or, you can do like you were doing but if the query "timer.objects.get(pk=1)" fails, for example, you send back a boolean flag response. So, when it is OK you redirect to the page you prefer.
I hope it could be useful to you!
If I understand rightly, you're sniffing the return code in the JavaScript, and then redirecting depending on the results.
You can do a redirect from Django, so I would do that instead of worrying about return codes. When you've got both a "flag" and a "ret_status", that is a hint you should re-think your design. :)
Also, shadowing the built-in dict object in the Python code should be avoided.