Bad request Json to Flask ajax - python

My Jquery code:
var obj_submit = {
email_p : $($('.form-group').find("input[name='email_p']")[0]).val(),
email_a : $($('.form-group').find("input[name='email_a']")[0]).val()
}
var json_submit = JSON.stringify(obj_submit);
$.ajax({
type: 'GET',
url: url,
contentType: 'application/json',
dataType: 'json',
data: json_submit
My python code:
`#app.route('/admission', methods=["GET", "POST"])
def admission():
form = FormFieldsAdmissao()
print (request.is_json)
content = request.get_json()
print (content)
return 'JSON posted'`
in the browser console I receive: GET [...] 400 (BAD REQUEST)
(the number of questions on the same subject is impressive, it makes me think it was something that should be simpler, since everyone has questions about it)

Related

Django: ajax not returning or sending any data in django

i am creating a simple like button with ajax, i have followed the tutorial but it seems, that i am missing something, i am not getting any error either in the console in my django terminal but when i click the button no data get sent, evrything just remains the same way, and this is not what i am expecting, i know i am missing something somewhere and i cannot really tell where this error is coming from.
views.py
#login_required
def like(request):
if request.POST.get("action") == 'post':
result = ""
id = int(request.POST.get('courseid'))
course = get_object_or_404(Course, id=id)
if course.like.filter(id=request.user.id).exists():
course.like.remove(request.user)
course.like_count -= 1
result = course.like_count
course.save()
else:
course.like.add(request.user)
course.like_count += 1
result = course.like_count
course.save()
return JsonResponse({'result': result})
urls.py NOTE:I don't know if i need a slug in this url path
path('like/', views.like, name="like"),
base.html
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
course-detail.html
<li><button id="like-button" value="{{course.id}}">like</button><span id="like-count">{{course.llke_count}}</span></li>
<script type="text/javascript">
$(document).on("click", '#like-button', function(e){
e.preventDefault()
$.ajax({
type: 'POST',
url: '{% url 'course:like' course.slug %}',
data: {
courseid: $('#like-button').val(),
csrfmiddlewaretoken: $("input[name=csrfmiddlewaretoken]").val(),
action: 'post'
},
success: function(json){
document.getElementById("like-count").innerHTML = json['result']
console.log(json)
},
error: function (xhr, errmsg, err)
console.log(xhr)
console.log(errmsg)
console.log(err)
})
})
</script>
this is all the code i have written for the functionality, if there is any other thing to be provided i will update the question
UPDATE AFTER FIRST ANSWER
#####################################################################
Now when i click the like button is does show an visible error but the like count now shows undefined and in my chrome dev tools is shows failed to load response data because this request was redirected
Update your code like this and I've doubt about your like table provide that inside your question.
inside your views.py
#login_required
def like(request):
if request.method == 'POST':
result = ""
course_id = int(request.POST.get('courseid'))
course = get_object_or_404(Course, id=course_id)
if course.like.filter(id=request.user.id).exists():
course.like.remove(request.user)
course.like_count -= 1
result = course.like_count
course.save()
else:
course.like.add(request.user)
course.like_count += 1
result = course.like_count
course.save()
return JsonResponse({'result': result})
inside your course-detail.html
<script type="text/javascript">
$("#like-button").on("click", function (e) {
e.preventDefault()
$.ajax({
type: 'POST',
url: "{% url 'course:like' %}",
data: {
courseid: $('#like-button').val(),
csrfmiddlewaretoken: "{{ csrf_token }}",
},
success: function (json) {
document.getElementById("like-count").innerHTML = json['result']
console.log(json)
},
error: function (xhr, errmsg, err) {
console.log(xhr)
console.log(errmsg)
console.log(err)
}
})
})
</script>
Note :
You don't have to check for action instead you can check for method eg. request.method.
You've provided wrong url inside your ajax call '{% url 'course:like' course.slug %}' it should be '{% url 'course:like' %}' without passing slug.
Do not use id as avariable because it will conflict with python id() function, you can check for all available built-in functions in python here.

Python string is null but also isn't None nor empty string

class StartAnalysis(BaseHandler):
def post(self):
playlist = self.request.get('playlist')
language = self.request.get('language')
If I make a POST request without this playlist field, then this happens:
>>> playlist
null
>>> type(playlist)
<type 'unicode'>
>>> playlist is None
False
>>> not playlist
False
>>> playlist == ''
False
>>> playlist == u''
False
How am I supposed to check that it's None? And why is it saying that it's null and not None?
I'm using AppEngine.
My javascript code making the POST request:
let params = new URLSearchParams(location.search);
let url_id = params.get('id');
let url_language = params.get('language');
const url = 'http://localhost:8080/start-analysis?playlist=' + url_id + '&language=' + url_language;
$.ajax({
url: url,
type: 'POST',
success: function(results) {
...
},
error: function(error) {
...
}
});
I changed to using application/json for the POST requests instead of the default application/x-www-form-urlencoded and that seemed to fix the problem of the request sending the string "null" instead of just an empty string when one of the parameters was empty or missing.
let params = new URLSearchParams(location.search);
let url_id = params.get('id');
let url_language = params.get('language');
const url = 'http://localhost:8080/start-analysis';
$.ajax({
url: url,
type: 'POST',
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify({'playlist': url_id,'language': url_language}),
success: function(results) {
...
},
error: function(response, status, error) {
...
}
});
And the backend receives it like:
class StartAnalysis(BaseHandler):
def post(self):
data = json.loads(self.request.body)
playlist = data['playlist']
language = data['language']

Bottle POST method - getting query parameters

I am trying to send a POST AJAX request to a Bottle server and read query_string parameters.
This works with GET method, but with POST, bottle.request.query_string is empty.
This is with python 3.6.8. Bottle version in 0.12.17
I'm stuck, please advise.
Bottle server:
#!/usr/bin/env python3
import bottle
print(bottle.__version__)
class EnableCors(object):
name = "enable_cors"
api = 2
def apply(self, fn, context):
def _enable_cors(*args, **kwargs):
bottle.response.headers["Access-Control-Allow-Origin"] = "*"
bottle.response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, OPTIONS"
bottle.response.headers["Access-Control-Allow-Headers"] = "Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token"
if bottle.request.method != "OPTIONS":
return fn(*args, **kwargs)
return _enable_cors
application = bottle.app()
application.install(EnableCors())
#application.route("/api/params", method=['OPTIONS', 'POST'])
def Api_Params():
print('bottle.request.query_string:', bottle.request.query_string)
bottle.run(host='0.0.0.0', port=8080, debug=True, reloader=True)
Test javscript client:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<script>
function test_post_param() {
var data = {'e': 'E', 'f': 'F', 'g': {'aa':'AA', 'bb':'BB'}};
$.ajax({
url: 'http://127.0.0.1:8080/api/params',
method: "POST",
data: "key=a",
// contentType: "text/plain",
success: function (response, textStatus) {
console.debug("test_post_param OK");
console.debug(textStatus);
console.debug(response);
},
error: function (response, textStatus) {
console.debug("test_post_param ERR");
console.debug(textStatus);
console.debug(response);
},
})
}
window.onload = test_post_param;
</script>
</body>
</html>
I put this on all my API endpoints. I am combining the POST form and query encoding into a single dict.
def merge_dicts(*args):
result = {}
for dictionary in args:
result.update(dictionary)
return result
payload = merge_dicts(dict(request.forms), dict(request.query.decode()))
So your code would look like this:
#application.route("/api/params", method=['OPTIONS', 'POST'])
def Api_Params():
payload = merge_dicts(dict(request.forms), dict(request.query.decode()))
print('bottle.request.query_string: {}'.format(payload))
Here is an example sending the data as JSON to a POST route which I have used successfully.
The JQuery AJAX call:
function test_post_param() {
var data = {'e': 'E', 'f': 'F', 'g': {'aa':'AA', 'bb':'BB'}};
$.ajax({
url: 'http://127.0.0.1:8080/api/params',
method: "POST",
data: JSON.stringify({
"key": "a"
}),
cache: false,
contentType: "application/json",
dataType: "json",
success: function(data, status, xhr){
// Your success code
},
error: function(xhr, status, error) {
// Your error code
}
})
};
The Bottle route:
#application.route("/api/params", method=['POST'])
def Api_Params():
key = bottle.request.forms.get("key")
print(key) # This should print 'a'
I prefer from bottle import route, get, post, template, static_file, request as the import statement. This allows the route to be written more simply (in my opinion).
#post("/api/params")
def Api_Params():
key = request.forms.get("key")
print(key) # This should print 'a'

Download CSV file to the client

I have the following route:
#app.route('/download/', methods=['GET'])
def download():
output_filename = request.args.get('output_filename')
data = dict(foos=[1,2,3,3,2,1], bars=[7,7,7,7,7,7])
df = pd.DataFrame(data)
result = df.to_csv(index=False)
response = make_response(result)
response.headers['Content-Disposition'] = f'attachment; filename={output_filename}'
response.headers['Cache-Control'] = 'must-revalidate'
response.headers['Pragma'] = 'must-revalidate'
response.headers['Content-type'] = 'application/csv'
return response
which I'm calling with AJAX as follows:
function download(data, handler = null) {
let data = {output_filename: "foo.csv"};
let url = "/download/";
$.ajax({
type: "GET",
url: url,
data: data,
success: function(data) {
console.log('success');
},
});
}
However, nothing's appearing on the client side. Am I missing something here?
Im more familiar with node than ajax ( i had the same issue in nodejs which i fixed here on stackoverflow), but maybe this will help:
$.ajax({
async: false,
from How do I make jQuery wait for an Ajax call to finish before it returns?

AJAX/PYTHON : how to send json value to server

I am a new to Ajax/Python, I don't know how to POST a json value to my python server.
Python code:
#app.route('/ajouterContact', methods = ['POST'])
def ajouterContact():
data = json.loads(request.data)
#nom = request.form['nomContact'];
contact.append(data)
ajouter.make_response(json.dumps(contact), 201)
ajouter.headers['Content-Type'] = 'application/json'
JS code
$('#buttonAjouter').click(function() {
var nom = 'Tom';
var myObj = new Object();
myObj.nom = nom;
var jsonText = JSON.stringify(myObj);
var i = 0;
$.ajax({
url: '/ajouterContact',
data: jsonText,
type: 'POST',
dataType: "json",
success: function(response) {
console.log(response);
},
error: function(error) {
console.log(error);
}
});
});
I am getting this error on server side :
ValueError: No JSON object could be decoded
If anyone can help me on this..
Thank you!
You need to provide the contentType in your ajax request:
contentType: 'application/json;charset=UTF-8',
Then in your server try to debug something like this:
request.json

Categories