I have an ajax js function:
if (data.result == "Successfully joined"){
window.location.href='{{ url_for( 'chat', name = "test" ) }}';
}
and function in python:
#app.route('/chat/<string:name>')
def chat(name):
return render_template("chat.html", c=name, s="Janek")
but when my first (ajax js) is called, it results with 404 not found error. After removing additional variable name, everythink loads corectly. What am I doing wrong?
EDIT 1
the entire js is:
<script type=text/javascript>
$(function() {
$('a#join_btn').bind('click', function() {
$.post('/', {
var1: $('input[name="cname"]').val(),
}, function(data) {
$('#result').text(data.result);
if (data.result == "Successfully joined"){
window.location.href='{{ url_for( 'chat', name = "test" ) }}';
}
});
return false;
});
});
</script>
SOLVED:
adding methods=["POST"] to #app.route('/') fixed the error for me.
#app.route('/chat/<string:name>') should be #app.route('/chat/<name>')
Related
I have a python script running in views.py within Django which returns two very large string arrays, x and y. It currently is able to run off a button press within my index.html.
def python_file(request):
final()
return HttpResponse("ran")
The ajax code I have running to do the button press.
<script src="http://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script>
function gotoPython(){
$.ajax({
url: "/python_file",
context: document.body
}).done(function() {
alert('finished python script');
});
}
</script>
It's also attached to the URLS.py. I know there's no array being returned right now, because I am unsure how to run the script, get the data simultaneously, then add it to the page without refreshing the page. So, I am asking what would be the best practice to do what I described. Any help would be appreciated.
This is generally what I do, not sure if it's best practice, but I return it with Json
I included two examples, and POST and a GET.
I also included some other stuff I usually return status and msg. When I catch an error or have an invalid POST I send back status = False and msg = '{error message}, then I can show that error message in the front end with Javascript. I keep this standardized in my project, but you do you.
def python_file(request):
xArray, yArray = final()
import json
data = {
'status': True, # True=All Good. False=Caught Error but didn't crash.
'x': xArray,
'y': yArray,
'msg': 'returning x and y arrays',
}
return HttpResponse(
json.dumps(data),
content_type="application/json"
)
function gotoPython(){
$.ajax({
method: 'GET',
url: '/python_file',
success: function(data){
console.log(data)
if (data['status']){
// do things with arrays
data['x']
data['y']
}else{
console.log('Server Replied with Error, but did not Crash');
console.log(data['msg']);
};
},
error: function(event,xhr,settings,errorText){
// general `xhr.status` Key for common errors
// 0 = Server didn't Reply (Server Down)
// 400 = Bad Request (Syntax Error)
// 403 = Forbidden (Login Token Expired or not in Group)
// 403 = Not Found (Invalid Url)
// 500 = Server Error (Django Crash)
},
});
};
function gotoPythonWithData(){
// if you wanted to POST data to this function you'd just do
// Note: Requires csrfmiddlewaretoken in template
// Throw this anywhere (it's hidden): {% csrf_token %}
submitData = {
'return_item_count': 25,
'csrfmiddlewaretoken': $('[name=\'csrfmiddlewaretoken\']').val(),
};
$.ajax({
method: 'POST',
url: '/python_file',
data: submitData,
success: function(data){
if (data['status']{
// do stuff
}else{
console.log(data['msg']);
};
},
error: function(event,xhr,settings,errorText){
},
});
};
Note: Some things like, Django Decimal objects, can not be be put into a Json Dump. In the Decimal example you've got to turn them into a Float or an Int
You can add parameters to the ajax.done(function) in order to get what your server returned.
$.ajax({
url: "/python_file",
context: document.body
}).done(function (response, textStatus, jqXHR) {
// What happens when the call is successful (200 <= status code < 300
console.log(response); // Logs what you returned from your django
// x + "separator" + y
})
.fail(function (jqXHR, textStatus, errorThrown) {
// Status code over 400
})
.always(function (jqXHR, textStatus, errorThrown) {
// Always happens
...
});
You can check ajax documentation here : https://api.jquery.com/jquery.ajax/#jQuery-ajax-settings-settings
And your django view should return some text content :
def view(response):
// code
return HttpResponse(status=200, content=x + "separator" + y)
This is Ajax code in my application, it adds object in Model without refreshing the page and shows no error:
$(document).on('submit', '#addbookform', function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: "{% url 'books:home' %}",
data: {
name: $('#name').val(),
price: $('#price').val(),
num_of_pages: $('#num_of_pages').val(),
csrfmiddlewaretoken: "{{ csrf_token }}"
},
success: function () {
alert('Form submitted successfully!!');
}
})
})
I tried to convert it to JavaScript, however it add objects to model, but it refreshes the page and moreover it shows a 403 error in console and then fade away.
document.querySelector('#addbookform').onsubmit = savebook;
function savebook() {
const name = document.querySelector('#name').value;
const price = document.querySelector('#price').value;
const num_of_pages = document.querySelector('#num_of_pages').value;
const url = "{% url 'books:home' %}"
const xhr = new XMLHttpRequest();
xhr.onload = function () {
if (this.status == 200) {
alert("Saved!");
}
}
xhr.open('POST', url, true);
xhr.send();
}
Can you please help me solve it?
Trying to get json data to front end and have tried a bunch of versions of axios requests but keep getting 404 status code.
This is an example of the front end format:
class App extends Component {
constructor () {
super();
this.state = {
message: ''
};
this.handleClick = this.handleClick.bind(this);
}
handleClick () {
axios.get('./hello')
.then(response => {
this.setState({ message: response.data.text });
})
.catch(error => {
console.log(error);
});
}
render () {
return (
<div className="button-container">
<button className='button' onClick={this.handleClick}>Click Me</button>
<p>{this.state.message}</p>
</div>
)
}
}
and back end routing:
#app.route('/hello')
def hello_world():
return jsonify(text='hello world')
Error message says 'Failed to load resource: the server responded with a status of 404 (Not Found)' or says http://localhost:5003/hello doesn't exist
First check your server, which url and port, your api is exposed
You need to pass complete url to axios constructor otherwise it will send request to same origin/url where your client is hosted, .e.g webapp at localhost:3000.
So your code will be
const SERVER_URL = 'http:localhost:5000'
axios.get(`${SERVER_URL}/hello`)
I am trying to upload many files at once to my CherryPy server.
I am following this tutorial that shows PHP code on the server side.
The JavaScript part is simple. Here is a summary of what it does:
function FileSelectHandler(e) {
var files = e.target.files || e.dataTransfer.files;
for (var i = 0, f; f = files[i]; i++) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "upload", true);
xhr.setRequestHeader("X_FILENAME", file.name);
xhr.send(file);
}
I translated the upload.php described in the tutorial into something like this:
def upload(self):
[...]
When the server receives the request I can see that cherrypy.request.headers['Content-Length'] == 5676
which is the length of the file I'm trying to upload, so I assume the whole file has been sent to the server.
How do I get the content of the file?
At its minimum it looks like the following. Tested in Firefox and Chromium. If you need to support legacy browsers I'd look at some JavaScript library for polyfills and fallback.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import shutil
import cherrypy
config = {
'global' : {
'server.socket_host' : '127.0.0.1',
'server.socket_port' : 8080,
'server.thread_pool' : 8,
}
}
class App:
#cherrypy.expose
def index(self):
return '''<!DOCTYPE html>
<html>
<head>
<title>CherryPy Async Upload</title>
</head>
<body>
<form id='upload' action=''>
<label for='fileselect'>Files to upload:</label>
<input type='file' id='fileselect' multiple='multiple' />
</form>
<script type='text/javascript'>
function upload(file)
{
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', function(event)
{
console.log('progess', file.name, event.loaded, event.total);
});
xhr.addEventListener('readystatechange', function(event)
{
console.log(
'ready state',
file.name,
xhr.readyState,
xhr.readyState == 4 && xhr.status
);
});
xhr.open('POST', '/upload', true);
xhr.setRequestHeader('X-Filename', file.name);
console.log('sending', file.name, file);
xhr.send(file);
}
var select = document.getElementById('fileselect');
var form = document.getElementById('upload')
select.addEventListener('change', function(event)
{
for(var i = 0; i < event.target.files.length; i += 1)
{
upload(event.target.files[i]);
}
form.reset();
});
</script>
</body>
</html>
'''
#cherrypy.expose
def upload(self):
'''Handle non-multipart upload'''
filename = os.path.basename(cherrypy.request.headers['x-filename'])
destination = os.path.join('/home/user', filename)
with open(destination, 'wb') as f:
shutil.copyfileobj(cherrypy.request.body, f)
if __name__ == '__main__':
cherrypy.quickstart(App(), '/', config)
I'm dealing with the problem I've seen some people also struggling. I need some functionality based on Facebook like buttons events. So I catch the event of clicking button and on it call my function with ajax. But on each single click my function is called multiple times, varying from 3 to 8. Problem is that this function creates models that ought to be unique, and because of the instant multiple call - I get multiple objects.
How to prevent this ? I've tried setting global var, but without any luck :
def send_submission(request):
global BLOCKED
if BLOCKED == 0:
logging.debug("should be locked")
BLOCKED = 1
(... do something...)
BLOCKED = 0
html = render_page(request)
ajax = simplejson.dumps({
"html": html
}, cls=LazyEncoder)
return HttpResponse(ajax, mimetype='application/javascript')
And the js grabbing the call:
FB.Event.subscribe('edge.create', function(href, widget) {
$.ajax({
type: "POST",
url: "/submissions/add",
data: "href="+href+"&ip={{ IP_ADDRESS }}",
dataType: 'json',
success: function(data){
$("#submissions").html(data["html"])
}
});
return false;
});
I've tried locking it with js, but it does not work either.
<script type="text/javascript">
window.fbAsyncInit = function() {
var maxAjaxCallAllowed=1;
var openAjaxCalls = new Array();
function insertHtml(data){
openAjaxCalls.pop();
$(".list-submissions").html(data["html"])
}
FB.init({appId: '161771113844567', status: true, cookie: true, xfbml: true});
FB.Event.subscribe('edge.create', function(href, widget) {
alert("glos");
if(openAjaxCalls.length < maxAjaxCallAllowed){
openAjaxCalls.push(1);
$.ajax({
type: "POST",
url: "{% url register_vote %}",
data: "href="+href+"&ip={{ IP_ADDRESS }}",
dataType: 'json',
success: function(data){
insertHtml(data);
}
});
}
else{
alert('Server call not possible at this time');
}
});
};
(function() {
var e = document.createElement('script');
e.type = 'text/javascript';
e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
e.async = true;
document.getElementById('fb-root').appendChild(e);
}());
</script>
If I am getting your issue correct, I think you should define a global variable in javascript. Say you have a global variable busy which should be set once a request is sent and unset when the request is completed.
Before every request you should check whether the variable is set and if its set do not send the request again.