How to iterate through multiple database servers in Flask Mysqldb - python

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

Related

how to declare cursor in flask_mysqldb for only once

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

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)

GET request with parameters FlasK/Rest API

I am trying to do a GET request which should print a specific row from my database depending on what arguments are set. The argument should be a name of a course and I want it to get all data from the selected course. It might be a bit easier to explain this as a SQL query. The query could look like this "SELECT * FROM courselist WHERE course='D0024E';"
where "course".
I have managed to do a fetchall() and receive all rows from a specific table, but I have not managed to get the parameters working correctly so I can get information from a specific course.
from flask import Flask
from flask import render_template
import requests
from flask import request
from flask import jsonify
import mysql.connector
app = Flask(__name__)
mydb = mysql.connector.connect(user='Mille',
auth_plugin='mysql_native_password',
password='jagheter12',
host='localhost',
database='paraplyet')
#app.route('/')
def index():
return render_template("index2.html")
#app.route('/courses', methods= ["GET"])
def getStudentInCourse():
myCursor2 = mydb.cursor()
query2 = ("SELECT * FROM paraplyet.kursinfo")
myCursor2.execute(query2)
myresult2 = myCursor2.fetchall()
return jsonify(myresult2)
if __name__ == '__main__':
app.run()
You need to update your route url to receive parameters
#app.route('/courses/<course_code>', methods= ["GET"])
def getStudentInCourse(course_code):
Then you can use this course_code to filter result.
Actually there are several points where your code(s) can fail, because establishing a correct front-end back-end chain in Flask is a little tricky (but worth it at the end).
You have a counter part front-end HTML code where you start your request with the proper variable, like "course" in your example, which may looks like this:
<form action="/courses" method="post">
<input>
<button type="submit"></button>
</form>
Then Flask as back-end will get this variable(parameter) as part of your query string as part of the URL string. You can retrieve this parameter in the form:
course = request.form.get('course')
To achieve it you have to add "POST" the view's methods, as it handles only "GET"-s as default.
#app.route('/courses', methods=["GET", "POST"])
Then you can use this variable as you want to complete your back-end operations:
query2 = ("SELECT * FROM courseInfo where courseCode = '" + course + "';")
those results then you can pass it back to the front-end via:
return jsonify(myresult2)
Your python/flask code should be some like as follows:
from flask import Flask
from flask import render_template
import requests
from flask import request
from flask import jsonify
import mysql.connector
app = Flask(__name__)
mydb = mysql.connector.connect(user='Mille',
auth_plugin='mysql_native_password',
password='jagheter12',
host='localhost',
database='paraplyet')
#app.route('/')
def index():
return render_template("index2.html")
#app.route('/courses', methods= ["GET", "POST"])
def getStudentInCourse():
if request.method == "POST" and request.form.get('course') != '':
myCursor2 = mydb.cursor()
course = request.form.get('course')
query2 = ("SELECT * FROM courseInfo where courseCode = '" + course + "';")
myresult2 = myCursor2.execute(query2)
return jsonify(myresult2)
if __name__ == '__main__':
app.run()

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.

Flask + MySQL strange behaviour

I am building a simple web-app which uses existing MySQL DB. It is my first time using Flask and I have been struggling to understand what I am doing wrong for the past couple of hours.
My simple project structure:
/root
/app
__init__.py
db.py
forms.py
views.py
/templates
base.html
index.html
login.html
config.py
run.py
I am trying to query my MySQL DB and fill the template with the result from the query.
My db.py:
from app import app
from flaskext.mysql import MySQL
class DB(object):
mysql = MySQL()
def __init__(self):
app.config['MYSQL_DATABASE_USER'] = 'loguser'
app.config['MYSQL_DATABASE_PASSWORD'] = 'asdzxc'
app.config['MYSQL_DATABASE_DB'] = 'log'
app.config['MYSQL_DATABASE_HOST'] = '127.0.0.1'
app.config['MYSQL_DATABASE_PORT'] = 33006
self.mysql.init_app(app)
def query_db(self):
cursor = self.mysql.connect().cursor()
cursor.execute("SELECT name from users limit 1")
data = cursor.fetchone()
if data is None:
return "No results from query"
else:
return data
And in my views.py I have the following:
from flask import render_template, flash, redirect
from app import app
from .forms import LoginForm
from .db import DB
#app.route('/')
#app.route('/index')
def index():
db = DB()
user = db.query_db()
print(user) (it prints it here so the db connection works)
posts = [ # fake array of posts
{
'author': {'nickname': 'John'},
'body': 'Beautiful day in Portland!'
},
{
'author': {'nickname': 'Susan'},
'body': 'The Avengers movie was so cool!'
}
]
return render_template("index.html",
title='Home',
user=user,
posts=posts)
I get "AssertionError" when I try to assign "user" to the user from the template:
AssertionError: A setup function was called after the first request was handled. This usually indicates a bug in the application where a module was not imported and decorators or other functionality was called too late.To fix this make sure to import all your view modules, database models and everything related at a central place before the application starts serving requests.
I believe I am violating a major principle of the framework. What is the correct way to pass the data to the template?
It is better to use Flask-SQLAlchemy and MySQL-python 1.2 , Successful code and documentation is available on the link below.
http://techarena51.com/index.php/flask-sqlalchemy-tutorial/
From my experience I found that MySQl support is not that good for python 3 atleast, it is better to use PostgreSQL, but that's just my personal opinion.
It's very late to give answer, but it may help someone.
You've to connect to MySQL before adding any route source to an API.
It should be in the order of
# 1. MySQL setup should be done at first
app = Flask(__name__)
api = Api(app)
mysql = MySQL()
app.config['MYSQL_DATABASE_USER'] = 'root'
app.config['MYSQL_DATABASE_PASSWORD'] = 'root'
app.config['MYSQL_DATABASE_DB'] = 'DataBase'
app.config['MYSQL_DATABASE_HOST'] = 'localhost'
mysql.init_app(app)
conn = mysql.connect()
cursor = conn.cursor()
# 2. Create API resource after that
api.add_resource(CreateUser, '/CreateUser')

Categories

Resources