How to use Flask with mysql (without sqlalchemy - raw sql query)? - python

I'm learning Flask framework. How to use Flask with mysql (without sqlalchemy - raw sql query)?
Here is example from official tutorial, how to configure it to use mysql?
from sqlite3 import dbapi2 as sqlite3
from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash
# create our little application :)
app = Flask(__name__)
# Load default config and override config from an environment variable
app.config.update(dict(
DATABASE='/tmp/firma.db',
DEBUG=True,
SECRET_KEY='development key',
USERNAME='admin',
PASSWORD='default'
))
app.config.from_envvar('FIRMA_SETTINGS', silent=True)
def connect_db():
"""Connects to the specific database."""
rv = sqlite3.connect(app.config['DATABASE'])
rv.row_factory = sqlite3.Row
return rv
def init_db():
"""Creates the database tables."""
with app.app_context():
db = get_db()
with app.open_resource('firma.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()
def get_db():
"""Opens a new database connection if there is none yet for the
current application context.
"""
if not hasattr(g, 'sqlite_db'):
g.sqlite_db = connect_db()
return g.sqlite_db
#app.teardown_appcontext
def close_db(error):
"""Closes the database again at the end of the request."""
if hasattr(g, 'sqlite_db'):
g.sqlite_db.close()
#app.route('/')
def show_entries():
db = get_db()
cur = db.execute('select title, text from entries order by id desc')
entries = cur.fetchall()
return render_template('show_entries.html', entries=entries)
...
How to configure it to use mysql?

You need a mysql driver. Python doesn't come with one by default. You'll have to install a 3rd party library like MySQLdb. Even if you use an ORM like sqlalchemy, you'll still need to install the driver. Also, you can run raw SQL with sqlalchemy.

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)

Where is the name of a database file to be created specified?

From http://flask.pocoo.org/docs/1.0/tutorial/database/
import sqlite3
import click
from flask import current_app, g
from flask.cli import with_appcontext
def get_db():
if 'db' not in g:
g.db = sqlite3.connect(
current_app.config['DATABASE'],
detect_types=sqlite3.PARSE_DECLTYPES
)
g.db.row_factory = sqlite3.Row
return g.db
def close_db(e=None):
db = g.pop('db', None)
if db is not None:
db.close()
...
def init_db():
db = get_db()
with current_app.open_resource('schema.sql') as f:
db.executescript(f.read().decode('utf8'))
#click.command('init-db')
#with_appcontext
def init_db_command():
"""Clear the existing data and create new tables."""
init_db()
click.echo('Initialized the database.')
...
def init_app(app):
app.teardown_appcontext(close_db)
app.cli.add_command(init_db_command)
...
def create_app():
app = ...
# existing code omitted
from . import db
db.init_app(app)
return app
Run the init-db command:
flask init-db
Initialized the database.
There will now be a flaskr.sqlite file in the instance folder in
your project.
I am surprised that flaskr.sqlite seems created without being specified any where. How it is specified to be created?
How is the name of the file flaskr.sqlite specified to sqlite3 when creating the file?
If using sqlite directly without flask, how can I create such a file named flaskr.sqlite?
Thanks.
See the previous page of the Tutorial, Application Setup, where app.config.from_mapping() happens.

How to close db with flask_mongoengine?

I am learning to use flask and flask_mongoengine to create a website. Follow the flask tutorial 1.0.2 version. But I ran into a problem, how to implement the get_db() and close_db() function?
Currently, what I am doing is :
myapp.py
....
def create_app():
app = Flask(__name__)
from db import db
db.init_app(app)
#app.route('/')
def home():
...
return app
db.py
from flask import g
from flask_mongoengine import MongoEngine
db = MongoEngine()
def get_db():
g.db = ???
return g.db
def close_db():
db = g.pop('db', None)
if db is not None:
??? # db.close() doesn't exist!!!
I am very confused about how to do this part. Can someone give any suggestions? In flask_mongoengine tutorial page, they don't implement the get_db() and close_db() ...
Confusion happens because in those tutorials there are too many programming patterns. In flask-1.0.2 tutorial they use getter method pattern and but flask-mongoengine relies on bootstraping a db to flask-app-instance, which relies on a builder pattern — Flask Application Factories. It may still be confusing but I'll show you how it's meant to be done.
Bootstrap a flask-mongoengine in create_app:
def create_app(test_config=None):
app = Flask(__name__)
# configure mongo settings here like in flask-mongoengine docs
g.db = db = MongoEngine()
db.init_app(app)
def get_db():
return g.db
def close_db():
pass
What's about close_db()? Well, that function exists in case db you've chosen needs some cleanup actions to be closed. But I haven't found in mongoengine docs any explicit mention that mongoengine db connection need a cleanup actions from you to be closed, so you can just pass it.

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