I'm using a Flask route to update a MYSQL database and I use an AJAX call to trigger this event. Whenever I run the webpage, I get an internal server error because it appends ?bet=1 to my url [and the is not a defined url]. I don't really get what I have to do to make this not happen and it to just run the normal route as defined in my python file. I've read a lot, but I'm not a programmer [I'm a scientist] and I don't know why this is happening. I think that when I submit the AJAX url it automatically updates the url with the data. Thanks for you help.
Custom.py route that I use with Flask
#custom_code.route('/saveddd', methods=['POST','GET'])
def savdict():
# get form data from ajax
#bet = request.form['bet']
try:
bet = request.form['bet']
db_url = "mysql+pymysql://root:Password!#127.0.0.1:3306/mydatabase"
table_name = 'my_experiment_table'
data_column_name = 'datastring'
# boilerplace sqlalchemy setup
# boilerplace sqlalchemy setup
engine = create_engine(db_url, echo=True)#altered by adding echo
conn=engine.connect()
metadata = MetaData()
metadata.bind = engine
existingtable2 = Table('dictatordecisions', metadata, autoload=True)
#print(existingtable2)
#print ("1")
insort = existingtable2.insert().values(Bet = bet)
#fire = sqlalchemy.sql.expression.insert(existingtable2, values=.5, inline=False, bind=None, prefixes=None, returning=None, return_defaults=False)
conn.execute(insort)
return "cool it worked"
except TemplateNotFound:
abort(404)
AJAX call
function death6(){
//var dictoatorresult = 0
//var selfammount = sliderfoo.value;
if (sliderfoo.value == "") {
alert ("please complete the task")
} else {dictatorchoice = sliderfoo.value;
psiTurk.recordTrialData({'phase':'DictatorGame','status':'submit','choice':dictatorchoice});
psiTurk.recordUnstructuredData('dictatordecision', dictatorchoice);
psiTurk.recordUnstructuredData('dice rolls purchased', purchase);
psiTurk.recordUnstructuredData('race manipulation if 1, plant if 2', condition);
psiTurk.recordUnstructuredData('race answers', RaceAnswers);
psiTurk.saveData();
$.ajax({})
$.ajax({
cache: true,
Type:'POST',
url:'/saveddd',
async: false,
data :{"bet" : dictatorchoice},
//crossDomain: true,
//async: false,
dataType: 'text'
//processData: false,
//beforeSend: function (xhr) {
//xhr.setRequestHeader("x-ajax-call", "no-cache");
})
;
psiTurk.showPage('postquestionnaire.html')
}
//d3.selectAll("input").remove();
//d3.selectAll("input").remove();
//d3.selectAll("div").remove();
}
Button maker
function makeButton2(text, callback){
d3.select("body")
.insert("p")
.insert("p")
d3.select("body")
.insert("button")
.attr("type", "button")
.attr("class", "btn btn-primary btn-lg")
.text(text)
.on("click", function(d){callback();});
}
Sliderfoo defined
var sliderSlide = document.createElement("input");
sliderSlide.setAttribute("type","number");
sliderSlide.setAttribute("fontsize","500px");
sliderSlide.setAttribute("min","0.00");
sliderSlide.setAttribute("max","1.00");
sliderSlide.setAttribute("step","0.01");
//sliderSlide.setAttribute("placeholder","0.50");
sliderSlide.setAttribute("id","sliderfoo");
sliderSlide.setAttribute("style", "font-size:25px")
//sliderSlide.setAttribute("syle","width: 300px");
//sliderSlide.setAttribute("width","400")
?bet=1 means you send it as GET, not POST.
Problem can be bacuse you used Type: 'POST' but it should be method: 'POST'.
You could also use directly $.post() instead of $.ajax()
Related
I am having a problem getting both of these submissions to work. I will search with one and it will be successful then when I refresh and try to search with the other one I get a url not found error. Been fighting with this all day thank you for your help
<playlist>
<input id = "url2" type = "text" name = "url"
placeholder = "Genre">
<input type = "submit" name = "button" onclick =
"test()">.
<script>
function test() {
var url2= document.getElementById("url2").value;
document.write("Generating Playlist");
setTimeout(function(){window.location=
"http://127.0.0.1:5000/recommend/genre/"+url2;}, 3000);
}
</script>
Sorry I'm new to this I didn't realize I wasn't allowed to post screenshots yet. I have 2 of these submissions one with /genre and the other with /limit, when they are alone in the code they work but when I have both of them in there one of them gives me a URL error. Here is the genre function in python.
"test()">.
#app.route("/recommend/genre/<seed_genres>")
def recommend_two(seed_genres):
endpoint_url = "https://api.spotify.com/v1/recommendations?"
limit=2
market="US"
#seed_genres="indie"
target_danceability=0.9
combo = ""
q=drake&type=artist&limit=5'
query = f'{endpoint_url}limit={limit}&market={market}&seed_genres=.
{seed_genres}&target_danceability={target_danceability}'
token = getAccessToken(clientID, clientSecret)
response =requests.get(query,
headers={"Content-Type":"application/json",
"Authorization":"Bearer " + token})
json_response = response.json()
head_one = "<h1/>"
head_two = "</h2"
for i in json_response['tracks']:
combo += (f"\"{i['name']}\" by {i['artists'][0]['name']}")
return (head_one+combo+head_two)
I'm trying to access a mysql database inside an ios app and I would like to use python to read and write to the database when called from my app.
PHP Code I would like to turn into a python script
I am not sure how to write or read data from my application using mysql-connector.
I believe this is done with the $_POST[a]; but I am not sure how to get the same results using python.
I also have a sample of how I am trying to send data from my app to my database written in swiftui.
'''
import Foundation
import SwiftUI
struct CreateEventButton: View {
#State private var isPresentedEvent = false
#State private var eventid: Int = 0
#State private var eventName: String = ""
#State private var eventDescription: String = ""
#State private var selectedStartTime = Date()
#State private var selectedEndTime = Date()
#Binding var annotationSelected: Bool
func send(_ sender: Any) {
let request = NSMutableURLRequest(url: NSURL(string: "http://YOUR FILE PATH")! as URL)
request.httpMethod = "POST"
let postString = "a=\(self.eventid)&b=\(self.eventName)&=c\(self.eventDescription)&=d\(self.selectedStartTime)&=e\(self.selectedEndTime)"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
print("error=\(String(describing: error))")
return
}
print("response = \(String(describing: response))")
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("responseString = \(String(describing: responseString))")
}
task.resume()
self.eventName = ""
self.eventDescription = ""
self.selectedStartTime = Date()
self.selectedEndTime = Date()
}
var body: some View {
Button(action: {
self.isPresentedEvent.toggle() //trigger modal
}, label: {
Text("Create Event")})
.foregroundColor(.secondary)
.background(Color(.secondarySystemBackground))
.cornerRadius(50.0)
.sheet(isPresented: $isPresentedEvent, content:{
VStack{
TextField("Event Name", text: self.$eventName).padding()
TextField("Event Description", text: self.$eventDescription).padding()
Form {
DatePicker("When your event starts: ", selection: self.$selectedStartTime, in: Date()...)
}
Form {
DatePicker("When your event ends: ", selection: self.$selectedEndTime, in: Date()...)
}
HStack{
Button(action: {
self.isPresentedEvent.toggle()
self.annotationSelected = false
self.eventid += 1
print("Start: \(self.selectedStartTime)")
print("End: \(self.selectedEndTime)")
//send()
}, label: {
Text("Create Event")
})
Button(action: {
self.isPresentedEvent.toggle()
}, label: {
Text("Cancel")
})
}
Text("Create Event Button (Non Functional)").padding()
}
} )
}
}
'''
I am not sure what parameters to put in the sender function created here.
Any insight would be greatly appreciated.
In order to receive POST requests from the SwiiftUI app, you need to run a python webserver like flask.
1. Create a python module (file) something like this:
app.py
from flask import Flask
from flask import make_response
import mysql.connector
from flask import request
server_name = "localhost"
username = "flask"
password = "flask"
dbname = "flask"
# Create and check connection
try:
conn = mysql.connector.connect(
host=server_name,
user=username,
passwd=password,
database=dbname
)
print("Connection OK")
except e:
print("Connection failed: ", e)
mycursor = conn.cursor()
app = Flask(__name__)
#app.route('/', methods=['POST'])
def register():
name = request.form['a']
age = request.form['b']
sql = "INSERT INTO users (name, age) VALUES (%s, %s)"
val = (name, age)
try:
mycursor.execute(sql, val)
conn.commit()
conn.close()
except e:
print("Error: ", e)
return make_response("Success!", 200)
2. Make sure you have the necessary libraries installed:
pip install flask
pip install mysql-connector-python
You need to make sure your MySQL database is up and that you fill in the real credentials for the database in the code. (Default MySQL port = 3306)
3. Start the flask development webserver
export FLASK_APP=app.py # OR set FLASK_APP=app.py (for Windows)
python -m flask run
Your server should start at: http://localhost:5000
Replace: http://YOUR FILE PATH with http://localhost:5000/ in your swift code example and viola!
UPDATE: I tested this and it works. Here is the swiftUI code I generated in postman:
import Foundation
var semaphore = DispatchSemaphore (value: 0)
let parameters = "a=Lance&b=35"
let postData = parameters.data(using: .utf8)
var request = URLRequest(url: URL(string: "http://localhost:5000/")!,timeoutInterval: Double.infinity)
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print(String(describing: error))
return
}
print(String(data: data, encoding: .utf8)!)
semaphore.signal()
}
task.resume()
semaphore.wait()
The API returns both JSON and also render the template and when i call $.getJSON it will only return that render template but not JSON value. I have tried this
if request.args['type'] == 'json':
return json.dumps(group)
else:
return render_template("/c.., summary=json.dumps(group))
but it says
bad request
Is there any way I can get that JSON value whenever I need it?
This is my view
#cms.route('/add/asset/<client_id>', methods=["GET"])
#login_required
def asset_add(client_id):
if int(current_user.id_) == int(client_id):
group = {}
group['id'] = []
group['pid'] = []
group['name'] = []
for index in range(len([r.id_ for r in db.session.query(Assetgroup.id_)])):
for asset in (Assetgroup.query.filter_by(parent_id=(index or ''))):
group['id'].append(asset.id_)
group['pid'].append(asset.parent_id)
group['name'].append(asset.name)
if request.args['type'] == 'json':
return json.dumps(group)
else:
return render_template("/cms/asset_add.html", action="/add/asset", asset=None,
client_id=client_id,
types=Type.query.all())
else:
return 'permission denied'
and this is my ajax request
$(document).ready(function () {
$('#group_id').click(function () {
$.getJSON(
'/add/asset/' + {{ client_id }},
function (data) {
$('#group_id').find('option').remove();
var len = data.id.length;
for (var i = 0; i < len; i++) {
var option_item = '<option value="' + data.id[i] + '">' + data.name[i] + "</option>";
$('#group_id').append(option_item);
}
}
);
});
});
You can add parameter in html call to get the json result...
i.e)
const Endpoint = '/add/asset/?'
$.getJSON(Endpoint, {type: 'json'}).done(function(data...)
I believe this is what you are looking for
http://flask.pocoo.org/docs/0.12/api/#flask.Request.is_json
That is a flask method that checks if the request is json
Then you can use jsonify still in flask to return json (you need to import it though)
from flask import jsonify
so your code becomes
if request.is_json:
return jsonify(group)
Hope you find that useful and more elegant
One of the easier ways to debug is just return json alone for a start to see how the response looks in a browser. So you can remove login required (assuming you are not yet in production), do not check if the request is_json, then call the api and see what it returns. So assuming your client id is 1
#cms.route('/add/asset/<client_id>', methods=["GET"])
def asset_add(client_id):
if int(current_user.id_) == int(client_id):
group = {}
group['id'] = []
group['pid'] = []
group['name'] = []
for index in range(len([r.id_ for r in db.session.query(Assetgroup.id_)])):
for asset in (Assetgroup.query.filter_by(parent_id=(index or ''))):
group['id'].append(asset.id_)
group['pid'].append(asset.parent_id)
group['name'].append(asset.name)
return jsonify(group)
Now you can visit http://yoursite.com/add/asset/1 to see your response
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
});
I'm working on validating my webapp, which is using Turbogears 2.3.3 and formencode 1.3
I want to validate a dynamic form that the user has created through a form creation process.
I'm sending the form fields from the client to the server using json to help organize things.
Here is how I'm sending the data:
var dataToSend = JSON.stringify({
'num_of_copies': num_of_copies.val(),
'amountAnswers' : amountAnswers,
'yesNoAnswers' : yesNoAnswers,
'selectAnswers' : selectAnswers,
'comments':comments.val()
})
$.ajax({
type: 'POST',
url: siteProxy+'orders/saveOrderItem',
data: {'data':dataToSend},
dataType: "json",
success: function (data, textStatus) {
if (textStatus == "success") {
if (data.errors){
console.log(data.errors)
}
}
},
error: function (data, textStatus) {
alert('error');
}
})
On The server I want to validate the data and then do some stuff
#expose('json')
#validate(validators=orderItemSchema(),error_handler=simpleErrorHandler)
def saveOrderItem(self,**kw):
answers = json.loads(kw['data'])
...... do stuff ...
Without the validations, my code works.
Here is my validation Schema:
class orderItemSchema(Schema):
def _convert_to_python(self, value_dict, state):
value_dict = json.loads(value_dict['data'])
super(orderItemSchema,self)._convert_to_python(value_dict, state)
num_of_copies = validators.Number(min=1)
comments = validators.UnicodeString()
amountAnswers = ForEach(AmountAnswerValidator())
yesNoAnswers = ForEach(YesNoAnswerValidator())
selectAnswers = ForEach(SelectAnswerValidator())
The validation works well.
My problem is this: after the validation, kw turns to none, and I can't do stuff in
def saveOrderItem(self,**kw):
I think the problem lies somewhere in this part of the code:
class orderItemSchema(Schema):
def _convert_to_python(self, value_dict, state):
value_dict = json.loads(value_dict['data'])
super(orderItemSchema,self)._convert_to_python(value_dict, state)
Thanks for the help
Probably orderItemSchema._convert_to_python is missing return value. Should be return super(orderItemSchema,self)._convert_to_python(value_dict, state) or you will be returning None as the converted value.
If you are using a recent tg version I suggest you also have a look at #decode_params decorator ( http://turbogears.readthedocs.org/en/latest/reference/classes.html#tg.decorators.decode_params ), it will extract the controller parameters from the json body and let validation flow as usual. It will avoid the two json.load in your code.