The way I send one data to flask
.js
function func(s) {
let toPost = {name: f.name, sf: split.f};
let jsonStr = JSON.stringify(toPost);
$.ajax({
url: "temp",
type: "POST",
data: JSON.stringify(data),
processData: false,
contentType: "application/json; charset=UTF-8",
success: function(){
console.log("success")
}
});
}
.py
#app.route('/temp', methods = ['POST'])
def temp() :
jsonStr = request.get_json()
file_object = open('temp.txt', 'a')
file_object.write(jsonStr)
file_object.write("\n")
file_object.close()
return render_template('temp.txt')
But I would like to send multiple data, so the ajax look like this:
data: {str: JSON.stringify(data), method: "add"}
Everything else remains the same.
In the .py file how could I get both str and method as well?
errors
console
jquery-3.2.1.min.js:4 POST FILENAME 400 (BAD REQUEST)
com
127.0.0.1 - - [] "POST /FILENAME HTTP/1.1" 400 -
full error
Your code leaves a lot of room for speculation.
The error message you get results from the fact that you want to send data as JSON but do not format it completely compliantly.
Normally, submitted objects are automatically sent as form data and formatted accordingly beforehand. You suppress this behavior by setting the processData parameter to false. However, this also means that the formatting to JSON must also be done by you. Otherwise a string representation of the transferred object would be sent, which the server cannot interpret.
As the following example shows, you should convert all data to JSON using JSON.stringify(...) before sending it.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Index</title>
<style media="screen">
output {
white-space: pre;
}
</style>
</head>
<body>
<form name="my-form">
<input type="text" name="name" />
<input type="text" name="sf" />
<input type="submit" />
</form>
<output name="result"></output>
<script
src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
crossorigin="anonymous"></script>
<script type="text/javascript">
$(document).ready(() => {
$('form[name="my-form"]').submit(function(evt) {
evt.preventDefault();
const form = $(this);
const formData = {};
$.each(form.serializeArray(), (_, row) => {
formData[row.name] = row.value;
});
// => { name: <anything>, sf: <something> }
console.log(formData);
const method = 'add';
const data = { data: formData, method: method };
// => { data: { name: <anything>, sf: <something> }, method: "add" }
console.log(data);
$.ajax({
url: '/temp',
type: 'post',
data: JSON.stringify(data),
contentType: 'application/json; charset=utf-8',
processData: false
}).done(data => {
$('output[name="result"]').html(data);
});
});
});
</script>
</body>
</html>
Depending on the requirements, you can query the data on the server side using its key, since it has already been parsed from the JSON format.
Since you get a dict for your nested object because of this, a conversion to a string is necessary before you can write it to the file.
import json, os
from flask import (
Flask,
render_template,
request
)
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/temp', methods=['POST'])
def temp():
data = request.json.get('data')
method = request.json.get('method', 'add')
if method == 'add' and data:
path = os.path.join(app.static_folder, 'temp.txt')
with open(path, 'a') as fp:
print(json.dumps(data), file=fp)
return app.send_static_file('temp.txt')
Please note that this is a simplified example trying to be based on your specifications.
Related
View.py
def export(request):
if request.is_ajax():
ourid = request.GET.getlist("terid")
Case_Detail = Case_Info_Resource()
for i in ourid:
print(i)
queryset = Case_Info.objects.filter(id=i)
dataset = Case_Detail.export(queryset)
response = HttpResponse(
dataset.xls, content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename="persons.xls"'
print("breakpoint")
return response
Ajax Script
<script>
$(document).ready(function () {
$('#Download').click(function () {
var list = [];
$("input:checkbox[name='checkbox']:checked").each(function () {
list.push($(this).val());
});
$.ajax({
url: '/Account_Manager/Download/',
type: 'GET',
data: { 'terid': list },
traditional: true,
dataType: 'html',
success: function () {
alert("The best cricketers are: " + list.join(", "));
}
});
});
});
</script>
Error:
The view Apps.views.export didn't return an HttpResponse object. It returned None instead.
So, Ajax wants us to return the value in HttpResponse but I need to pass the response normally in order to download the excel which I am creating. I think I checked all the possible answers and struggling with it from the last 3 days. Thank you in advance for any help, suggestions, or edit.
html-javascript
var csrftoken = $('[name="csrfmiddlewaretoken"]').val();
$('#Save').click(function () {
var ajaxdata = {
exam: $('#Exam').val()
};
$.ajax({
url: '/save',
type: 'POST',
dataType: 'json',
data: JSON.stringify(ajaxdata),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
"X-CSRFToken": csrftoken
},
credentials: 'include',
success: function () {
alert(ajaxdata);
console.log(ajaxdata);
},
error:function (xhr, ajaxOptions, thrownError){
console.log(ajaxdata);
}
});
}
views.py
import json
from django.http import HttpResponse
def save(request=request):
data = json.loads(request.body)
testexam = data['exam']
testexam = request.POST.get('exam')
testobj = MyObject.objects.filter(name="David").first()
testobj.Exam = testexam
testobj.save()
return HttpResponse(json.dumps({"success": True}), content_type="application/json")
These are my html and views now.
Removed the "flask" part.
data = json.loads(request.body)
allowed me to receive data successfully!
Still don't quite understand why " request.POST " didn't work.
I'll come back later to update if I manage to know the reason!
Thanks for the comments and useful suggestions!
No need using the flask.
This is how I receive the data:
data = json.loads(request.body)
and it all works well!
Thanks for all the comments, suggestions, answers! Really appreciated!
your ajax code is just fine, however you're doing few things wrong. First of all, in your html part.
<h1> This is simple html</h1>
<input type="text" id = "Exam">
<button type="button" id="Save">Save</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
var csrftoken = $('[name="csrfmiddlewaretoken"]').val();
$('#Save').click(function () {
var ajaxdata = {
exam: $('#Exam').val()
};
$.ajax({
url: '/save',
type: 'POST',
dataType: 'json',
data: JSON.stringify(ajaxdata),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
"X-CSRFToken": csrftoken
},
credentials: 'include',
success: function () {
alert(ajaxdata)
},
error:function (xhr, ajaxOptions, thrownError){
console.log("this is an error")
}
});
});
</script>
You were initiating the ajaxdata before the click event happened, which may lead to the null value of #Exam filed.
Now getting back to your Flask part, you can't do request.POST with the data sent through Ajax request. Rather you can access all the data you sent through your js with request.data, below is the code which is working successfully.
from flask import Flask, request,send_from_directory
import json
# set the project root directory as the static folder, you can set others.
app = Flask(__name__)
#app.route('/home')
def root():
#return "this is home"
return send_from_directory("/home/ekbana/Documents/","index.html")
#app.route('/save',methods=['POST'])
def save(request=request):
print(request.data.decode("utf-8")) #We need to decode because it's a byte
#not a string
data = json.loads(request.data.decode("utf-8"))
#data here is {'exam': 'a text'} a dict in this case
testexam = data["exam"]
testobj = MyObject.objects.filter(name="David").first()
testobj.Exam = testexam
testobj.save()
return HttpResponse(json.dumps({"success": True}), content_type="application/json")
This is working fine with me, I replicated a simple example for your requirement. Aslo make sure to use methods=["POST"] if you want your route to recieve the POST request, if you didn't specify it, it may lead to HTTP_405_METHOD_NOT_ALLOWED.
I am pretty new to Django and I am trying to figure out how to add content dynamically coming from a python script without reloading a page.
Currently, I have two functions in my views.py file. One handles uploading a file (home), and the other handles calling a python script and handling the file (handle). The reason I separated it like this is because I want to sequentially populate a HTML table as the python script works with the uploaded file.
However, my ajax function is not receiving any data from the handle function's http response and I am not sure why. Neither the success nor the error functions are being called. This is really strange because the print statement in the handle function in views.py prints successfully with data.
Views.py
i=0
uploaded_file = None
def home(request):
if (request.method == 'POST'):
file_form = UploadFileForm(request.POST, request.FILES)
if file_form.is_valid():
global uploaded_file
uploaded_file = request.FILES['file']
print(uploaded_file)
else:
file_form = UploadFileForm()
return render(request, 'personal/home.html', {'form': file_form})
def handle(request):
# TODO make ajax wait for a response from 'home'
# so I don't have to wait for 1 second
time.sleep(1)
data = {}
data['Name'] = fileName(uploaded_file)
if(request.is_ajax()):
print(data) # prints succesfully
return HttpResponse(json.dumps(data),
content_type="application/json")
home.html
<script type = "text/javascript" language = "javascript">
function post_tables(data) {
alert(data)
}
$(document).ready(function(post_tables) {
$("#upload").click(function(event){
$.ajax( {
contentType: "application/json; charset=utf-8",
dataType: "json",
type: "get",
url:'/handler',
success: function(data) {
console.log("over here")
post_tables(data)
},
error: function(data) {
console.log("down here")
post_tables("error being thrown")
}
});
});
});
</script>
urls.py
urlpatterns = [
path(r'', views.home, name='home'),
path(r'handler', views.handle, name='handle'),
]
I explained the whole process ajax django to you. Perhaps your problem will be solved. good luck.
views.py
def handle(request):
if request.method == 'POST':
data = request.POST
field_example = data.get('field_example')
return JsonResponse(data)
else:
data = request.GET
field_example = data.get('field_example')
return JsonResponse(data)
home.html
<form id="upload">
{% csrf_token %}
<input type="text" name=field_example>
.
.
.
</form>
urls.py
urlpatterns = [
path(r'', views.home, name='home'),
path(r'handler/', views.handle, name='handle'),
]
js code in home.html:
$("#upload").submit(function (e) {
e.preventDefault();
var formData = new FormData(this);
$.ajax({
url: "{% url 'handle' %}",
type: 'GET',
data: formData,
cache: false,
contentType: false,
processData: false,
success: function (data) {
console.log("over here")
post_tables(data)
},
error: function (data) {
console.log("down here")
post_tables("error being thrown")
}
});
});
I'm trying to compile project https://github.com/kannan4k/django-carpool
please refer this project repo for this issue.
and end up with following error during ajax call.
Failed to load resource: the server responded with a status of 400 (BAD REQUEST).
I know this is because of ajax post request & CSRF tokens.
following is my setting.
1. disable "django.middleware.csrf.CsrfViewMiddleware"
2. in new_trip page I have a button (Postdata)so this button sends an ajax request.
My View:-
#login_required
def save_journey(request):
if request.is_ajax() and request.method == "POST":
try:
res = json.loads(request.body)
cords = res['cords']
cords = [[x['d'], x['e']] for x in cords]
distance = res['distance']
start_place = res['start']
end_place = res['end']
clusters = clusterize_latlngs(cords, distance)
time = datetime.datetime.strptime(res['time'], "%m/%d/%Y %H:%M")
Trip.objects.create(user=request.user, time=time, cluster=json.dumps(clusters), travel_distance=distance,
start_place=start_place, end_place=end_place)
return HttpResponse()
except:
return HttpResponseBadRequest()
else:
return HttpResponseNotAllowed(['POST'])
Ajax call (home.js)
function postData() {
radius = 0;
var url = "/save_journey/";
var dataType = 'json';
if (type == 'r') {
radius = $('#radius').val();
url = "/get_results/";
dataType = 'html';
}
var data = JSON.stringify({
cords: myroute,
time: document.getElementById('dateStart').value,
start: document.getElementById('startPlace').innerHTML,
end: document.getElementById('endPlace').innerHTML,
radius: radius,
distance: distance
});
$.ajax({
type: "POST",
url: url,
dataType: dataType,
data: data,
success: function (data) {
if (type == 'r') {
window.location.href = "/search_results/";
}
else {
window.location.href = '/trip_success/';
}
},
error: function () {
console.log('Error getting options list...')
}
});
console.log(data);
}
this code is not able to call /save_journey/ URL.
I tried many answers from stack overflow & didn't figure out what is the problem .
You should never disable csrftoken unless you're absolutely sure about what you're doing. It's an important part of the security features implemented in Django.
Here is an example of how you can use Ajax with Django with csrftoken:
You can use Ajax Post to send JSON to Django and then handle the arguments as a dict(). Here is an example:
In browser (JQuery/JavaScript):
function newModule() {
var my_data = $("#my_element").val(); // Whatever value you want to be sent.
$.ajax({
url: "{% url 'modules' %}", // Handler as defined in Django URLs.
type: "POST", // Method.
dataType: "json", // Format as JSON (Default).
data: {
path: my_data, // Dictionary key (JSON).
csrfmiddlewaretoken:
'{{ csrf_token }}' // Unique key.
},
success: function (json) {
// On success do this.
},
error: function (xhr, errmsg, err) {
// On failure do this.
}
});
In server engine (Python):
def handle(request):
# Post request containing the key.
if request.method == 'POST' and 'my_data' in request.POST.keys():
# Retrieving the value.
my_data = request.POST['my_data']
# ...
Hope this helps.
I´m building a social network with Grails and got stucked
on giving users inner their editprofile
page the chance to paste an youtube-Url into a textfield and by clicking a button a JS regexxes the id out of the URL pasted, an ajax post is fired updating a div with a preview image of the youtube video
the html looks like :
<g:textField name="videoinput" class="videoinput reLef" value="" />
<span class="daten_videouploadbtn reLef" ></span>
<g:render template="/forms/storedVideos" />
the JS looks like :
$('.daten_videouploadbtn').click(function() {
var string = document.editProfileForm.videoinput.value;
var neu = string.replace(/http[s]?:\/\/(?:[^\.]+\.)*(?:youtube\.com\/(?:v\/|watch\?(?:.*?\&)?v=|embed\/)|youtu.be\/)([\w\-\_]+)/i, '$1');
var id = RegExp.$1;
jQuery.ajax({
type:'POST',
data:RegExp.$1,
url:'${createLink(action: 'addVideo')}',
success:function(data,textStatus){jQuery('#storedvideos').html(data);},
error:function(XMLHttpRequest,textStatus,errorThrown){}
});
});
the controller looks like :
def addVideo() {
def videoitems = !!%%-- HOW TO PARSE YOUTUBE-ID HERE -%%!!
render(template:"/forms/storedVideos", model: [newVideo:videoitems])
}
and stored videos looks :
<div id="storedvideos"><span><img src="http://img.youtube.com/vi/${newVideo}/default.jpg" width="225px" height="130px"/></span></div>
i just dont get it how to catch the data of the Ajax Post and update the div with the preview image with the id inside,
can someone give a hint ? it is killing me
You should post the data like this:
jQuery.ajax({
type: 'POST',
data: { value: RegExp.$1 },
...
After that you can access the posted data inside your grails controller with params.value.
I got this working on Grails 2.0.4:
Javascript/Ajax
var data =
{requestId: 12456,
node: "node1",
host: "mynode.com"};
$.ajax({
url: '/myurl',
data: JSON.stringify(data),
type: 'post',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function() ...
},
error: function() ...
}
});
In Grails....
def service(){
def jsonObj = request.JSON
}
I like this approach because request.JSON parses the data and returns a ready to use object.