I am learning how to create a flask application that insert records un a mysql database whose values are obtained from an html form.
I have written the following piece of code:
from flask import Flask, render_template, request, redirect, url_for, flash
from flask_mysqldb import MySQL
app = Flask(__name__)
#MySql Connection
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'password'
app.config['MYSQL_DB'] = 'flaskcontacts'
mysql = MySQL(app)
# settings
app.secret_key = 'mysecretkey'
#app.route('/')
def Index():
return render_template('index.html')
#app.route('/add_contact', methods=['POST'])
def add_contact():
if request.method == 'POST':
fullname = str(request.form['fullname'])
phone = str(request.form['phone'])
email = str(request.form['email'])
cur = mysql.connect.cursor()
print(str(fullname), phone, email)
cur.execute("INSERT INTO flaskcontacts.contacts (fullname, phone, email) VALUES (%s, %s, %s)",
(fullname, phone, email))
mysql.connection.commit()
flash('Contact Added successfully')
return redirect(url_for('Index'))
Once I execute it I see that I obtain the message "Contact added succesfully" but I cannot see any record in the mysql database, however I see that the Id that is autoincremental, it is incremented. So if I update the table directly into the database it works and shows me a number of Id that was already autoincremented, as if the previous piece of code worked but it doesn't update it at all.
I have invested many hours trying to fix this problem, but apart from the answer I would appreciate if you can help me with some best practices of how to debug these type of problems.
Regards
MySQL will generate an auto-increment ID before it tries the INSERT. But the INSERT might fail, for example if the INSERT causes a constraint conflict, there will be no row created.
The auto-increment ID can't be "un-allocated" or otherwise pushed back into a collection of ID values to be handed out. Some other concurrent session might have allocated the next value already, and MySQL does not maintain a pool of ID values, it only knows about the latest value allocated per table.
So MySQL would have to wait until the INSERT had succeeded (including checking all constraints, executing any triggers, etc.), while blocking any other concurrent sessions from doing their INSERTs. Only then could it reliably allocate ID's without "wasting" any values.
That proved to be too constraining on parallelism for MySQL, so their compromise is to quickly allocate an ID, then unlock the auto-increment mechanism for that table, and allow concurrent sessions to proceed. THEN attempt the INSERT using the ID generated. This allows for greater throughput.
Your app prints "Contact Added successfully" even if the INSERT resulted in an error. You don't check for any error in the code you show above, so how do you know it was successful?
Anyway, you shouldn't worry about "wasted" ID values. They are not intended to be consecutive, only unique. If you feel you might run out of integers, then do the math. What is the maximum value of your integer column? What is the rate of generating new values? Based on these, you should be able to figure out how long you've got before you run out. This shouldn't be difficult for a software developer to do this simple math.
The problem was here in this line:
cur = mysql.connect.cursor()
That is inside the function add_contact.
The correct function to use is:
cur = mysql.connection.cursor()
So it was connection instead of connect.
Related
I have a Flask application with a dashboard running and some parts of the dashboard use a date as input form for filter data that comes from a database. But if the user does not enter the date as request arg then the route returns a template rendered with the last available date in the table gps_data.
I have the next route for the dashboard index which works as I want:
import psycopg2 as pg2
#bp.route("/index", methods=["GET", "POST"])
def index():
date = request.args.get("date") # date form input
imei = request.args.get("imei") # imei form input
# if the user request 'index' without any date use last date from the table gps_data
if not date:
cur = conn.cursor() # psycopg2 cursor to postgresql database
query = """SELECT
max(timestamp_utc::date)
FROM
gps_data
WHERE imei = imei%s
"""
try:
# gps_data_last_date
cur.execute(query, imei)
date = cur.fetchall()[0][0]
except Exception as e:
conn.rollback()
date = None
print(e)
else:
conn.commit()
return redirect(url_for("dashboard.index", date=date))
return render_template(
"dashboard.html",
date=date
)
But the problem is that I do not want to get the max date while the user loads the dashboard page, because the table gps_data is very big and the performance when loading the page could be affected. So I want to use a kind of background task that that updates the max date in a global variable or something similar (once per day for example), avoiding to query the database table gps_data.
I have done research about which is the best way to accomplish this and there seems to be two options:
Adding Celery + Redis, and set up a Celery periodic task in Flask, and then read the date in the view function from Redis.
Add a background thread to Flask like this answer and read the date in the view function from a global variable.
Keep using the SQL table gps_data but add an index on columns timestamp_utc and imei.
Do you know if there is any better or more efficient option than the these two? If there is no other, which one do you think would be the best of these two options?
EDIT: Added third option
I am looking for your help because i am getting this error on Python Flask:
pymysql.err.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Autoevaluacion', 'RT_Funcionarios', 'Reporteadores', 'Reporteadores_Gerentes', '' at line 1")
I am inserting data from Angular in my MySQL DB with the help of Flask, i am trying to insert the fields name, email, role and foros, this last one is filled with the elements of an array so when i tried to save the data, that error is shown.
this is my python code
#app.route('/insertarUsuario', methods = ["POST"])
def insertar_usuario():
conection = pymysql.connect('localhost', 'root','root', 'users')
data = request.json
print(data)
print(data['foros'])
cursor = conection.cursor()
sql_query ="INSERT INTO administrador_usuarios(nombre, email, rol, foros) VALUES ('" + str(data["nombre"]) + "','"+ str(data["email"])+"','"+str(data["rol"])+"', '"+ str(data["foros"])+"')"
cursor.execute(sql_query)
conection.commit()
response = "OK"
print("respuesta:",response)
return jsonify(response)
I would like to highlight 2 things:
1-. that array that will fill the field foros, it comes from the number of foros you select through checkboxes, so if i just check one, the register is saved but if i checked more than one, it crashes.
2-. i found out that if i replace
(data["foros"])
for
str("autoevaluacion" + "rt_funcionario")
it works so i think maybe it about how do i receive the array.
Can you help me please?. I am kinda new on Flask
I have an insert statement.
conn = sqlite3.connect('WO1.db')
with conn:
cur1 = conn.cursor()
cur1.execute("insert into workorder (Title, Link, Status)
values (?,?,?)", ('iijiji', 'ijjijijj', '22jhhuhij'))
if conn:
conn.close()
The title and link columns had UNIQUE constraints on them and I was getting the following error and my program terminated.
sqlite3.IntegrityError: UNIQUE constraint failed:
But 1 new record inserted into the database which is what I wanted.
I then created a new table where the Title and Link columns didn't have a UNIQUE constraint.
I ran the program again and this time received no error however, the record was inserted into the table twice which explains the error when there was UNIQUE constraints on the Link and Title.
Is there any logical explanation as to why this insert statement is executing twice?
Note This is only one place in the program where a connection is established, a query is executed and then the connection is closed. There is no other interaction with this database in the program other than the normal configuration.
I haven't had any other sessions open with this database either other than within this application.
I'm running this query in the python file where the program is run from.
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
conn = sqlite3.connect('WO1.db')
with conn:
cur1 = conn.cursor()
cur1.execute("insert into workorder (Title, Link, Status) values
(?,?,?)", ('en24433', 'www.reddit.com', 'Not Completed'))
if conn:
conn.close()
migrate = Migrate(app, db)
#app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run(host='localhost', port=8080, debug= True)
Your need to remake your database access code.
Firstly you connect twice at the same db by using the with statement after conn.connect().
When a database is accessed by multiple connections, and one of the processes modifies the database, the SQLite database is locked until that transaction is committed.
I think that this is the reason for your error.
After you make the insert in database you need to commit the changes.
This method commits the current transaction. If you don’t call this method, anything you did since the last call to commit() is not visible from other database connections. If you wonder why you don’t see the data you’ve written to the database, please check you didn’t forget to call this method.
Be aware that close() does not automatically commit:
This closes the database connection. Note that this does not automatically call commit(). If you just close your database connection without calling commit()first, your changes will be lost!
Take a look at sqlite3 API docs
It worked when I put the database connection and insert statements into my index route rather than above the routes.
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
#app.route('/')
def index():
conn = sqlite3.connect('WO1.db')
with conn:
cur1 = conn.cursor()
cur1.execute("insert into work_order (Title, Link, Status) values (?,?,?)",
('iikii', 'ijkoijj', '66hhuhij'))
conn.close()
return render_template('index.html')
I'm using flask to build a simple web app but for whatever reason the conn.commit() is not committing the data into the database. I know this because when I manually add something to the database the data doesn't change but the ID section increases each time I test it (because its using auto increment). So basically my current table has ID 1, Username test, Password test and the next entry that I inserted manually (after trying to use my application) was ID 5, Username blah, Password blah. Is there any specific reason that the commit isn't working?
EDIT: I had to change cursor = mysql.connect().cursor() to conn.cursor()
#app.route('/add_data/')
def add_tv_to_database():
conn = mysql.connect()
cursor = mysql.connect().cursor()
cursor.execute("INSERT INTO _accounts VALUES (null, 'test','test')")
conn.commit()
return render_template('index.html')
In the fourth line of your code, change it from cursor = mysql.connect().cursor() to cursor = conn.cursor(). This will ensure that the cursor uses the existing connection to database (from the previous line of code), instead of creating a new MySQL connection.
I'm creating an iOS client for App.net and I'm attempting to setup a push notification server. Currently my app can add a user's App.net account id (a string of numbers) and a APNS device token to a MySQL database on my server. It can also remove this data. I've adapted code from these two tutorials:
How To Write A Simple PHP/MySQL Web Service for an iOS App - raywenderlich.com
Apple Push Notification Services in iOS 6 Tutorial: Part 1/2 - raywenderlich.com
In addition, I've adapted this awesome python script to listen in to App.net's App Stream API.
My python is horrendous, as is my MySQL knowledge. What I'm trying to do is access the APNS device token for the accounts I need to notify. My database table has two fields/columns for each entry, one for user_id and a one for device_token. I'm not sure of the terminology, please let me know if I can clarify this.
I've been trying to use peewee to read from the database but I'm in way over my head. This is a test script with placeholder user_id:
import logging
from pprint import pprint
import peewee
from peewee import *
db = peewee.MySQLDatabase("...", host="localhost", user="...", passwd="...")
class MySQLModel(peewee.Model):
class Meta:
database = db
class Active_Users(MySQLModel):
user_id = peewee.CharField(primary_key=True)
device_token = peewee.CharField()
db.connect()
# This is the placeholder user_id
userID = '1234'
token = Active_Users.select().where(Active_Users.user_id == userID)
pprint(token)
This then prints out:
<class '__main__.User'> SELECT t1.`id`, t1.`user_id`, t1.`device_token` FROM `user` AS t1 WHERE (t1.`user_id` = %s) [u'1234']
If the code didn't make it clear, I'm trying to query the database for the row with the user_id of '1234' and I want to store the device_token of the same row (again, probably the wrong terminology) into a variable that I can use when I send the push notification later on in the script.
How do I correctly return the device_token? Also, would it be easier to forgo peewee and simply query the database using python-mysqldb? If that is the case, how would I go about doing that?
The call User.select().where(User.user_id == userID) returns a User object but you are assigning it to a variable called token as you're expecting just the device_token.
Your assignment should be this:
matching_users = Active_Users.select().where(Active_Users.user_id == userID) # returns an array of matching users even if there's just one
if matching_users is not None:
token = matching_users[0].device_token