flask_sqlalchemy with Oracle - python

I am working on to build a web application and using Oracle database with flask sqlalchemy. The connection is successful with my below code, but when i am running the code i am getting a warning as
SAWarning: Attribute 'CATEGORY' on class appears to be a non-schema 'sqlalchemy.sql.column()' object; this won't be part of the declarative mapping
My code is working and i am able to run the html, but i feel its the schema name which is missing in my connection. Below is my code. ( i have not mentioned the credentials and host name) does any one know where the schema needs to be declared or if any one can help resolve the warning.
below is the code i have created.
'''from flask import Flask, render_template, request
from flask_sqlalchemy import SQLAlchemy
from datetime import date, datetime
from sqlalchemy import create_engine
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI']= 'oracle://username:password#host:port/sid'
db = SQLAlchemy(app)
class Master_dates(db.Model):
DATA_DATE = db.Column(db.Integer, primary_key=True)
LOCATN = db.Column(db.String(80))
CATEGORY = db.column(db.String(120))
#app.route("/")
def home():
return render_template('index.html') '''

Using sqlalchemy i got the same error with the following code
class users(db.Model):
_id=db.Column("id", db.Integer, primary_key=True)
name=db.Column(db.String(100))
address=db.Column(db.String(100))
neighborhood=db.Column(db.String(100))
city=db.Column(db.String(100))
phone=db.Column(db.String(100))
document=db.Column(db.String(100))
passwoord=db.Column(db.String(100))
verifyPass=db.Column(db.String(100))
rol=db.Column(db.String(100))`
it got fixed when inside of the same class (in your case will be Master_dates(db.Model)) when i added a constructor to it. like this:
def __init__(self, name, address, neighborhood, city, phone, document, passwoord, rol):
self.name=name
self.address=address
self.neighborhood=neighborhood
self.city=city
self.phone=phone
self.document=document
self.passwoord=passwoord
self.rol=rol
you can try to add this piece of code on your Master_dates(db.Model) class
def __init__(self, DATA_DATE, LOCATN, CATEGORY):
self.DATA_DATE=DATA_DATE
self.LOCATN=LOCATN
self.CATEGORY=CATEGORY
I hope not to reach out here too late

Related

Flask_sqlalchemy, engine, session, connection and running SQL in my Flask app

I am beyond confused at this point. I have read so much documentation and there seems to be sparse examples of what to do for running raw SQL statements on my flask app using Flask_sqlalchemy or flask_mysqldb.
I have started by downloading XAMPP and creating a database on MySQL server through my localhost. I then created my flask application and created an initial database from the terminal using
>>> from yourapplication import db
>>> db.create_all()
The code from my flask app is as follows based on the documentation here
from flask import Flask, render_template, request, redirect, session
from flask_session import Session
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
from werkzeug.security import check_password_hash, generate_password_hash
# Set up Flask instance
app = Flask(__name__)
# Configure db
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root#localhost/hoook"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
# Reload templates when changed (take down when in production)
app.config["TEMPLATES_AUTO_RELOAD"] = True
# Configure session to use filesystem (instead of signed cookies)
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)
# Create db model
class Users(db.Model):
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.Text, nullable=False)
last_name = db.Column(db.Text, nullable=False)
email = db.Column(db.Text, unique=True, nullable=False)
password = db.Column(db.Text, nullable=False)
date = db.Column(db.DateTime, default=datetime.utcnow)
def __repr__(self):
return "<Users %r>" % self.id
great, now I can see my table in myPhpAdmin. I then ran a test statement to see if information would be added as follows
db.engine.execute("INSERT INTO users (first_name, last_name, email, password) VALUES ('chris', 'blah', 'blah#gmail.com', 'something')")
works! but then looking at the previous stackoverflow answer and then the subsequent documentation I find this method is depreciated therefore I cant use this going forward. So I try to use session.execute instead (since connection.execute also shows its depreciated) as I see that for some reason there are three different methods all with the same function execute() that can be used...???? source. So using the following statement I try to add another row to my table but it failed.
db.session.execute("INSERT INTO users (first_name, last_name, email, password) VALUES ('jeremy', 'blah', 'something#gmail.com', 'whatever')")
there were no error messages, just when I check my database, nothing new was added. So if I got this right engine.execute didnt need a connection but session does? Does that mean this line
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root#localhost/hoook"
is actually not connecting the session method to my database then? What about the pymysql connector in the URI? do I also need to import pymysql to be able to use this connector? What is the correct method for generating queries and being able to add tables etc from within your flask app... Please clarify as this is confusing and from my point of view, all this documentation and abstraction needs to be cleaned up.

sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) NOT NULL constraint failed: user.words

I've looked at the other posts with this same title, but they did not fix my problem. The error message in the above title is what I am getting.
I've made a simple database and constructor for the database. Just to test, I'm trying to add the word "hello" to the column "words" in the class User. But I keep getting this error. I've already tried putting autoincrement in the class column, but I ended it up getting another error. What is going wrong? Please see the code below. Python and Flask.
from flask import Flask, request, redirect, url_for, render_template
from datetime import datetime
from flask_sqlalchemy import SQLAlchemy
import sqlite3
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE URI"] = 'sqlite:///test.db'
db = SQLAlchemy(app)
class User(db.Model):
__tablename__ = 'user'
words = db.Column(db.String(200), primary_key=True)
def __init__(self, thewords):
self.thewords = thewords
db.create_all()
db.session.commit()
texts = "hello"
textstuffent = User(texts)
db.session.add(textstuffent)
db.session.commit()
results = User.query.all()
print(results)
#app.route('/', methods = ['POST', 'GET'])
def hello():
return render_template('Textarea.html')
app.run(debug=True)
For anyone who visits this page in the future, I've found what was wrong. I did not reference "words" as "self.words". My code now works and I am relieved to finally continue coding so that some other bug can confound me later down the road. Please see below. You can see the difference in code in the User class. I used query.all() to prove that data has made it into the database.
from flask import Flask, request, redirect, url_for, render_template
from datetime import datetime
from flask_sqlalchemy import SQLAlchemy
import sqlite3
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE URI"] = 'sqlite:///test.db'
db = SQLAlchemy(app)
class User(db.Model):
words = db.Column(db.String(200), primary_key=True, nullable=False)
def __init__(self, thewords):
self.words = thewords
db.create_all()
db.session.commit()
texts = "hello"
textstuffent = User(texts)
db.session.add(textstuffent)
db.session.commit()
print(User.query.all())
#app.route('/', methods = ['POST', 'GET'])
def hello():
return render_template('Textarea.html')
app.run(debug=True)

SQLAlchemy, Flask and extracting using filter_by and filter

I have a Flask application in which I am using SQLAlchemy.
I have a model:
from sqlalchemy import BigInteger, Column, JSON, Text
from app import db
class Table_910(db.Model):
__tablename__ = 'table_910'
id = db.Column(BigInteger, primary_key=True)
did = db.Column(Text)
timestamp = db.Column(BigInteger)
data = db.Column(JSON)
db_timestamp = db.Column(BigInteger)
def __repr__(self):
return '<1_Data %r, %r>' % (self.did, self.id)
In my views part I am trying to extract a set of rows based on did and timestamp as I only want a subset of data.
from flask import render_template
from app import app, db, models
#app.route('/')
#app.route('/index')
def index():
rows = models.Table_910.query \
.filter_by(did='357139052424715') \
.filter((db.Table_910.timestamp > 1466846920000) | (db.Table_910.timestamp < 1467017760000))
return render_template('index.html', rows=rows)
But for some reason I am getting:
AttibuteError: 'SQLAlchemy' object has no attribute 'Table_910'.
Does anyone know the reason behind this?
As the Error message states you try to access Tables_910 on the SQLAlchemy object. But your model is defined in the models.py. You need to use models.Table_910 for your query.

Using SQLAlchemy models in and out of Flask

I'm trying to build SQLAlchemy models that can be used in Flask and in other non-Flask services. I know that in order to use these objects in Flask I can use the Flask-SQLAlchemy module and build the models like this:
app_builder.py
def create_app(config):
# Create a Flask app from the passed in settings
app = Flask('web_service')
app.config.from_object(config)
# Attach SQLAlchemy to the application
from database import db
db.init_app(app)
database.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Job(db.Model):
__tablename__ = 'job'
job_id = db.Column(db.Integer, primary_key=True)
description = db.Column(db.String(256))
def __init__(self, description):
self.description = description
However it looks like doing this ties the models to using flask_sqlalchemy. I have another service that I would like to use these models in that don't use flask. Is there a way I can reuse these class definitions (maybe by changing db.Model) within a non-Flask specific context?
flask_sqlalchemy doesn`t allow you to use it outside of a Flask context. However, you can create models via SQLAlchemy itself. So your database.py file would look like this:
from sqlalchemy import MetaData, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
metadata = MetaData()
Base = declarative_base(metadata=metadata)
class Job(Base):
__tablename__ = 'job'
job_id = Column(Integer, primary_key=True)
description = Column(String(256))
def __init__(self, description):
self.description = description
You can initialize a flask_sqlalchemy object using produced metadata (flaskdb.py):
from flask_sqlalchemy import SQLAlchemy
from database import metadata
db = SQLAlchemy(metadata=metadata)
And you initialize your Flask app like this:
from flask import Flask
from flaskdb import db
def create_app(config):
app = Flask('web_service')
app.config.from_object(config)
db.init_app(app)
Created models can be used outside of the Flask context via a Session. For example:
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
from database import metadata, Job
engine = create_engine('your://database#configuration/here')
session = Session(engine)
jobs = session.query(Job).all()
session.close()
As a downside of this approach, you can't use direct access to database objects through models. Instead, you are forced to use Sessions:
from database import Job
from flaskdb import db
Job.query.all() # Does not work
db.session.query(Job).all() # Works

SQLAlchemy create_all() does not create tables

I'm trying to integrate PostgreSQL and SQLAlchemy but SQLAlchemy.create_all() is not creating any tables from my models.
My code:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2://login:pass#localhost/flask_app'
db = SQLAlchemy(app)
db.create_all()
db.session.commit()
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
def __init__(self, username, email):
self.username = username
self.email = email
def __repr__(self):
return '<User %r>' % self.username
admin = User('admin', 'admin#example.com')
guest = User('guest', 'guest#example.com')
db.session.add(admin)
db.session.add(guest)
db.session.commit()
users = User.query.all()
print users
But I get this error: sqlalchemy.exc.ProgrammingError: (ProgrammingError) relation "user" does not exist
How can I fix this?
You should put your model class before create_all() call, like this:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2://login:pass#localhost/flask_app'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
def __init__(self, username, email):
self.username = username
self.email = email
def __repr__(self):
return '<User %r>' % self.username
with app.app_context():
db.create_all()
db.session.add(User('admin', 'admin#example.com'))
db.session.add(User('guest', 'guest#example.com'))
db.session.commit()
users = User.query.all()
print(users)
If your models are declared in a separate module, import them before calling create_all().
Say, the User model is in a file called models.py,
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2://login:pass#localhost/flask_app'
db = SQLAlchemy(app)
# See important note below
from models import User
with app.app_context():
db.create_all()
db.session.add(User('admin', 'admin#example.com'))
db.session.add(User('guest', 'guest#example.com'))
db.session.commit()
users = User.query.all()
print(users)
Important note: It is important that you import your models after initializing the db object since, in your models.py you also need to import the db object from this module.
If someone is having issues with creating tables by using files dedicated to each model, be aware of running the "create_all" function from a file different from the one where that function is declared.
So, if the filesystem is like this:
Root
--app.py <-- file from which app will be run
--models
----user.py <-- file with "User" model
----order.py <-- file with "Order" model
----database.py <-- file with database and "create_all" function declaration
Be careful about calling the "create_all" function from app.py.
This concept is explained better by the answer to this thread posted by #SuperShoot
This is probably not the main reason why the create_all() method call doesn't work for people, but for me, the cobbled together instructions from various tutorials have it such that I was creating my db in a request context, meaning I have something like:
# lib/db.py
from flask import g, current_app
from flask_sqlalchemy import SQLAlchemy
def get_db():
if 'db' not in g:
g.db = SQLAlchemy(current_app)
return g.db
I also have a separate cli command that also does the create_all:
# tasks/db.py
from lib.db import get_db
#current_app.cli.command('init-db')
def init_db():
db = get_db()
db.create_all()
I also am using a application factory.
When the cli command is run, a new app context is used, which means a new db is used. Furthermore, in this world, an import model in the init_db method does not do anything, because it may be that your model file was already loaded(and associated with a separate db).
The fix that I came around to was to make sure that the db was a single global reference:
# lib/db.py
from flask import g, current_app
from flask_sqlalchemy import SQLAlchemy
db = None
def get_db():
global db
if not db:
db = SQLAlchemy(current_app)
return db
I have not dug deep enough into flask, sqlalchemy, or flask-sqlalchemy to understand if this means that requests to the db from multiple threads are safe, but if you're reading this you're likely stuck in the baby stages of understanding these concepts too.

Categories

Resources