how to declare cursor in flask_mysqldb for only once - python

I have this code(not complete)
#app.route('/', methods = ['GET','POST'])
def home():
"""
the main function for routing home
"""
if request.method == 'POST':
try:
if not cursor:
cursor = mysql.connection.cursor()
url = request.form.get('link',"")
the thing is i have to re declare cursor every time inside request.method=='POST' block
if i declare it outside(say first line) i got an error saying cursor not defined.because the post connection is not active yet

In Flask, you can use the before_request decorator to create a cursor
only once and reuse it in multiple routes. Here's an example: In this
example, the cursor is created using mysql.connection in the
before_request function, which runs before each request. The cursor is
then stored in g (the Flask global request object), so it can be
reused in multiple routes. The teardown_request function closes the
cursor and the connection after each request.
from flask import Flask
from flask_mysqldb import MySQL
app = Flask(__name__)
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'user'
app.config['MYSQL_PASSWORD'] = 'password'
app.config['MYSQL_DB'] = 'database'
mysql = MySQL(app)
#app.before_request
def before_request():
g.conn = mysql.connection
g.cursor = g.conn.cursor()
#app.teardown_request
def teardown_request(exception):
if hasattr(g, 'cursor'):
g.cursor.close()
if hasattr(g, 'conn'):
g.conn.close()
#app.route('/')
def index():
g.cursor.execute('SELECT * FROM table')
data = g.cursor.fetchall()
return data

Related

How to use Rest Api in app Flask for insert data to Database?

I have a app Flask. I want to use Rest api for insert data to Database. I have a app.pyfile and api.py file. I want to write a post method in api.py. I want to get information from client using add.html file and post it to api. then api this information add to Database. I use pyodbc for connect to SQL Server Database.in this Database, there is a table tbl_product with columns P_ID,title,count,price and active. I don't know, how do it. When I run python api.py on http://localhost:5000/add, I see { "message": "The method is not allowed for the requested URL."}. Also, When I run python app.py, on http://localhost:8080/addI see Method Not Allowed. The method is not allowed for the requested URL .
Can you help me?
my app.py file is:
from flask import Flask,render_template,url_for, request, redirect, flash, jsonify,json
import pyodbc
import requests
from api import ProductAdd
app = Flask(__name__)
app.secret_key= "flash_message"
# creating connection Object which will contain SQL Server Connection
conn = pyodbc.connect('Driver={SQL Server};'
'Server=TABRIZIYAN;'
'Database=market_DB;'
'Trusted_Connection=yes;')
cursor = conn.cursor()
#app.route('/add')
def add():
if request.method =='POST':
productDetails= request.form
title= productDetails['title']
count=productDetails['count']
price= productDetails['price']
active= productDetails['active']
create_row_data = { 'title':str(title), 'count':str(count),
'price':str(price), 'active':str(active) }
info = requests.post('http://localhost:5000/add', data= create_row_data)
return info.text #return(render_template('product.html'))
else:
return (render_template('add.html'))
if __name__=='__main__':
app.run(debug=True, port="8080")
my api.py file is:
from flask import Flask, request, render_template,url_for, redirect, flash
from flask_restplus import Api, Resource
from flask import jsonify
import pyodbc
import requests
flask_app = Flask(__name__)
api = Api(app=flask_app)
class ProductAdd(Resource):
def post(self):
productDetails= request.json
title= productDetails['title']
count=productDetails['count']
price= productDetails['price']
active= productDetails['active']
cursor = conn.cursor()
cursor.execute(" INSERT INTO Tbl_product(title, count, price, active) VALUES(?, ?, ?, ?)
",(title,count,price,active))
conn.commit()
resp = jsonify('User added successfully!')
resp.status_code = 200
return resp
api.add_resource(ProductAdd , '/add')
if __name__ == '__main__':
flask_app.run(debug=True)

How can I connect my flask app to my SQLite3 database?

Hi I am trying to create a customer feedback form; I have managed to create the pages I need, but I am having difficulty connecting my app to my SQLite3 database.
So in my code python code I am trying to collect the data from the customer feedback form and hold it in a database.
In the feedback form they will be prompted to input their name, choose some answers from a drop-box selection, and to write a comment at the end.
The answers will be housed in the database (for future reference - like reports etc) and the user will be redirected back to the home page where they will be able to see their name & comment (taken from the feedback form).
I have watched tutorials on sqlite3 which was kind of easy to understand & execute (a lot easier for me than MySQL) but I'm missing something because it won't connect to my database.
my python flask code:
from flask import Flask, render_template, redirect, url_for, request, session, flash, g
from functools import wraps
import sqlite3
app = Flask(__name__)
app.secret_key = "random_character_generator" # this would be random or anything the developer wants
app.database = "gymdatabase.db"
conn = sqlite3.connect(app.database)
c = conn.cursor()
def connect_db():
return sqlite3.connect(app.database)
#app.route('/')
def home():
g.db = connect_db()
cur = g.db.execute('select * from posts')
posts = [dict(name=row[0], welcome=row[1], equipment=row[2], cleanliness=row[3], interaction=row[4], comments=row[5], contact=row[6]) for row in cur.fetchall()]
g.db.close()
return render_template('gym_index.html', posts=posts)
#app.route('/feedback', methods=['POST'])
def feedback():
return render_template('gym_feedback.html')
#app.route('/process', methods=['GET', 'POST'])
def process():
g.db = connect_db()
name = request.form['name']
welcome = request.form['welcome']
equipment = request.form['equipment']
cleanliness = request.form['cleanliness']
interaction = request.form['interaction']
comment = request.form['comment']
contact = request.form['yes_no']
conn.commit()
cur = g.db.execute(select * from posts)
posts = [dict(name=row[0], welcome=row[1], equipment=row[2], cleanliness=row[3], interaction=row[4], comments=row[5], contact=row[6]) for row in cur.fetchall()]
g.db.close()
return redirect(url_for('home', posts=posts))
When I try to submit a feedback form I get:
sqlite3.ProgrammingError: SQLite objects created in a thread can only be used in that same thread.
I can upload the html file on request; I'm not too sure if I have space to do so along with my python file.
I think that this is due to your line conn.commit() in your process() function. You declare conn = sqlite3.connect(app.database) when Flask first starts, but each function defined with the #app.route(...) function decorator gets called in a different thread in response to HTTP requests (as defined in the aforementioned function decorator). You probably want to do something like this:
#app.route('/process', methods=['GET', 'POST'])
def process():
...
db = connect_db()
cur = db.cursor()
cur.execute("select * from posts")
results = cur.fetchall()
...
You can see this link for further documentation: https://docs.python.org/2/library/sqlite3.html
I can edit my answer if you provide more context regarding where your code is failing.

How to iterate through multiple database servers in Flask Mysqldb

I am looking to loop through 2 database servers to get a match for the query submitted through form(example.html) ie iterating the configuration value (app.config['MYSQL_HOST'] = db['mysql_host']). If no data is retrieved from first database server it needs to query with the second one. When I try to make a list to iterate through the mysql hosts,
it shows me TypeError: list indices must be integers or slices, not str.
Below is the work code when I set one database server in app.config['MYSQL_HOST'] = db['mysql_host']. db.yaml file contains the database server and configuration information.
from flask import Flask, render_template, request
from flask_mysqldb import MySQL
import yaml
import sys
app = Flask(__name__)
db = yaml.load(open('db.yaml'))
app.config['MYSQL_USER'] = db['mysql_user']
app.config['MYSQL_PASSWORD'] = db['mysql_password']
app.config['MYSQL_DB'] = db['mysql_db']
mysql = MySQL(app)
#app.route('/')
def dashboard():
return render_template('dashboard.html')
#app.route('/sdetails')
def sdetails():
return render_template('s.html')
#app.route('/s', methods = ['POST', 'GET'])
def s():
dbhosts = yaml.load(open('yamlsample.yaml'))
dbhosts = list(dbhosts)
if request.method == 'POST':
result = request.form
sname = request.form["Name"]
for i in dbhosts:
app.config['MYSQL_HOST'] = i
cur = mysql.connection.cursor()
slist=cur.execute(slist=cur.execute("select * from table1 WHERE table1.name LIKE '{}'".format(sname))
sdetails=cur.fetchall()
if sdetails != None:
return render_template('results.html', sdetails=sdetails)
else:
continue # I thought continue will take me to the next dbhost. But not happening.
if __name__ == '__main__':
app.run(debug = True)
I am making use of db.yaml only for database username,password and database server.
db.yaml
mysql_user: 'xxxx'
mysql_password: 'xxxxx'
mysql_db: 'xxxxx'
I am making use of yamlsample.yaml for iterating over DB hosts only.
yamlsample.yaml
192.168.1.10
192.168.1.11

Flask: Pass object between pages

i want to create a simple web application who use a connection to a vCenter Server, and i want to pass the variable connection between pages, instead of recreate this connection on every page.
This is the code:
#!/bin/env python
from flask import Flask, request, redirect, render_template, session
from flask import Flask, request, redirect, render_template, session
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired
from modulo import MyForm
from pyVim import connect
from pyVim.connect import SmartConnectNoSSL, Disconnect
from pyVmomi import vim
app = Flask(__name__)
#app.route('/')
def index():
return redirect('/submit')
#app.route('/submit', methods=('GET', 'POST')) #ENTER USERNAME AND PASSWORD, SAVE ON /SUCCESS
def submit():
form = MyForm()
if form.validate_on_submit():
return redirect('/success')
return render_template('submit.html', form=form)
#app.route('/success', methods=('GET', 'POST')) #ESTABILISH CONNECTION USING USERNAME AND PASSWORD CREDENTIALS
def success():
form = MyForm()
username = form.username.data
password = form.password.data
c = SmartConnectNoSSL(host='10.116.xxx.xxx', user=username, pwd=password)
datacenter = c.content.rootFolder.childEntity[0]
clusters = datacenter.hostFolder
cluster = clusters.childEntity[0]
esxi = cluster.host
return render_template('success.html', esxi=esxi)
#app.route('/hosts', methods=('GET', 'POST'))
def hosts():
macchine = request.form.getlist('host')
for i in esxi:
for x in macchine:
if i.name == x:
do something..
return FINISH
if __name__ == '__main__':
app.secret_key='Secret'
app.debug = True
app.run(host = '0.0.0.0', port = 3000)
i want to reuse the c variable (the connection to the server) in other pages, and the object who derived from this variable for example esxi (list of object).
if i run the code, flask say: global name 'esxi' is not defined
How can i do this?
In flask you can store variables on your app object and reuse them later. Example:
app = Flask(__name__)
app.c = SmartConnectNoSSL(host='10.116.xxx.xxx', user=username, pwd=password)
# You can now reuse the connection like so
datacenter = app.c.content.rootFolder.childEntity[0]

MySQLdb returning old data when used with Flask Post

I have a Flask website with a MySQL backend. I have a table called, users. It has two columns: username and name and one record:
name username
Jim testuser123
When a user clicks the button on the website, it updates the record to set the name to Bob then print all records where name = 'Bob'. Yet, it returns no results. If I refresh the connection before re-querying, then it does return one result as it should. Does the mdb.connect object cache data? How could it not be returning the correct results?
init.py:
import pandas as pd
import MySQLdb as mdb
from flask import Flask, render_template, request
def sql_con():
return mdb.connect(host='myhost', port=3306, user='root', passwd='root', db='db', use_unicode=True, charset="utf8")
app = Flask(__name__)
def update_record():
con = sql_con()
cur = con.cursor()
sql_string= "Update users set name = 'Bob' where username = 'testuser123'"
cur.execute(sql_string)
con.commit()
#app.route('/', methods=['GET', 'POST'])
def myroute():
con = sql_con()
if request.method == 'POST':
update_record()
print pd.read_sql("select * from users where name = 'Bob'", con=con)
return render_template('1.html')
app.run( debug=True, port=5050)
1.html
<html>
<body>
<form method="POST">
<button id="mybutton" name='btn' value="mybutton">Submit Data</button>
</form>
</body>
For this code to print one result, I must add con=sql_con() right after I call the update(), but before the print statement. Why is that?
In general it is a good practice to use an ORM binding (i.e. Falsk-SQLAlchemy) with web frameworks (manages connection pools, automates commit/rollback, ...) even if an ORM seems overkill for a simple application.
Otherwise, avoid using multiple connections to the same database in the same request if you prefer manage this at low level (database connections).
Try this instead:
import pandas as pd
import MySQLdb as mdb
from flask import Flask, render_template, request
def sql_con():
return mdb.connect(host='myhost', port=3306, user='root', passwd='root', db='db', use_unicode=True, charset="utf8")
app = Flask(__name__)
def update_record(con):
cur = con.cursor()
sql_string= "Update users set name = 'Bob' where username = 'testuser123'"
cur.execute(sql_string)
con.commit()
#app.route('/', methods=['GET', 'POST'])
def myroute():
con = sql_con()
if request.method == 'POST':
update_record(con)
print pd.read_sql("select * from users where name = 'Bob'", con=con)
return render_template('1.html')
app.run( debug=True, port=5050)
If you want to scale a real app based on such solution, you should consider pulling an opened connection from a global connections pool. Creating a new db connection (at each HTTP request) may be time expensive.

Categories

Resources