Flask, SQLAlchemy, Foreign Keys - python

Hello I have some Problem with some foreign keys.
I have something like this:
class Foo(db.Model):
"""The foo object."""
__tablename__ = 'foos_foo'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.Text, unique=True)
content = db.Column(db.Text)
bar = db.relationship('Bar', backref='bars_bar')
bar_id = db.Column(db.Integer, db.ForeignKey('bars_bar.id'))
class Bar(db.Model):
"""The bar object."""
__tablename__ = 'bars_bar'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Text, unique=True)
description = db.Column(db.Text)
status = db.Column(db.SmallInteger, default=NEW)
I use this configuration style: https://github.com/mitsuhiko/flask/wiki/Large-app-how-to
So I have something like this:
from app.foos.views import mod as foosModule
from app.bars.views import mod as barsModule
app.register_blueprint(foosModule)
app.register_blueprint(barsModule)
If I call like in the config style from Mitsuhiko, python shell.py, comes this error:
sqlalchemy.exc.OperationalError: (OperationalError) no such table: bars_bar u'SELECT bars_bar.id AS bars_bar_id, bars_bar.name AS bars_bar_name, bars_bar.description AS bars_bar_description, bars_bar.status AS bars_bar_status \nFROM bars_bar' ()
What goes on there? Yes the table is not there because I will create it? Is there a way to create some tables before some other? Or what do I wrong?
Thanks for your time!

Quoting Flask-SQLalchemy docs:
To create the initial database, just import the db object from a interactive Python shell and run the SQLAlchemy.create_all() method to create the tables and database:
from yourapplication import db
db.create_all()

Related

How can i do a relationship with multiple entities?

How can i link both entities with relationship with flask python?
for example i have this entity, here i am trying to link with user = relationship('User'), so i am getting error relation of relationship (btw: Grant, User, Client are in differents files )
from sqlalchemy.orm import relationship
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Grant(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(
db.Integer, db.ForeignKey('user.id', ondelete='CASCADE')
)
user = relationship('User')
this is the error:
sqlalchemy.exc.InvalidRequestError: When initializing mapper mapped class Grant->grant, expression 'User' failed to locate a name ('User'). If this is a class name, consider adding this relationship() to the <class 'model.Grant.Grant'> class after both dependent classes have been defined.
note: those are my anothers entities:
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(40), unique=True, index=True,
nullable=False)
def check_password(self, password):
return True
and this is the Client.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Client(db.Model):
name = db.Column(db.String(40))
client_id = db.Column(db.String(40), primary_key=True)
this is the error user = relationship('User') please helpme

Flask-Sqlalchemy create views with postgres

I am using a Flask-Sqlalchemy postgres database model with the following style:
class User(db.Model) // Holds the users
id = db.Column(db.Integer, primary_key=True)
...
class Track(db.Model) // Holds racing tracks
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255), nullable=False)
class Record(db.Model) // Hold users records on tracks
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey("user.id"), primary_key=True)
track_id = db.Column(db.Integer, db.ForeignKey("map.id"), primary_key=True)
time = db.Column(db.BigInteger, nullable=False)
My goal now would be to create a view which holds all Tracks completed by Users. In plain PostgresSQL it would look like this:
CREATE VIEW OR REPLACE user_tracks_finished AS
SELECT DISTINCT user_id, track_id
FROM record;
The User model would look something like this:
class User(db.Model) // Holds the users
id = db.Column(db.Integer, primary_key=True)
finished_tracks = db.relationship(...)
I can not any way to create views with the flask-sqlalchemy module. There is a sqlalchemy-views module, which I can not get to run in my flask app. Anybody got a good idea on how to model something like this? Any help ist appreciated!
I managed to get it done with SQLAlchemy-Utils: https://pypi.org/project/SQLAlchemy-Utils/
from sqlalchemy_utils import create_view
class UserFinishedMaps(db.Model):
__table__ = create_view(
name="user_finished_maps",
selectable=select([Record.user_id, Record.map_id]).group_by(
Record.user_id, Record.map_id
),
metadata=db.metadata,
)

SQLAlchemy Can't Find Column when adding ForeignKey to another table

I have been fighting this error for a few days now in a variety of configurations.
I tried adding Relationship lines under each of the ForeignKeys with no luck.
I also swapped my queries from using the declarative_base style calls to SQL queries.
The error only appears once I add the second ForeignKey to Task. (I originally had several foreign keys in Task and Project but pared things down until it worked and tried slowly adding things back. Adding the second ForeignKey did it no matter which table it was added to.)
My current Flask method is:
#app.route('/project/<int:project_id>/')
def showProject(project_id):
project = session.query(Project).from_statement(text("SELECT * FROM project WHERE project.id = project_id ORDER BY project.projnum DESC"))
tasks = session.query(Task).filter_by(project_id = project_id).all()
return render_template('project.html', project = project, tasks = tasks)
And I get a "no such column" error:
OperationalError: (sqlite3.OperationalError) no such column: task.project_id [SQL: u'SELECT task.id AS task_id, task.name AS task_name, task.description AS task_description, task.assigned_id AS task_assigned_id, task.project_id AS task_project_id, task.due AS task_due \nFROM task \nWHERE task.project_id = ?'] [parameters: (2,)]
This is the setup file for my database:
import os
import sys
import time
from sqlalchemy import Column, ForeignKey, Integer, String, Float
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy import create_engine
Base = declarative_base()
engine = create_engine('sqlite:///gmnpm.db')
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String(250), nullable=False)
email = Column(String(250), nullable=False)
picture = Column(String(250))
class Task(Base):
__tablename__ = 'task'
id = Column(Integer, primary_key=True)
name = Column(String(250), nullable=False)
description = Column(String(2000))
assigned_id = Column(Integer, ForeignKey('user.id'))
project_id = Column(Integer, ForeignKey('project.id'))
due = Column(Integer, default=int(time.time()))
class Project(Base):
__tablename__ = 'project'
id = Column(Integer, primary_key=True)
name = Column(String(250), nullable=False)
description = Column(String(1000))
projnum = Column(Integer)
Base.metadata.create_all(engine)
After reading a bunch of documentation and going crazy trying random things on the off chance they work, I'm grateful for any suggestions!

alembic autogenerate get the metadata for a Flask-SQLAlchemy bind

My flask application has a single database(db1) before, now I bind a new database(db2) to it, both has 10 tables.
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root#localhost:3306/db1'
SQLALCHEMY_BINDS = {
'test': 'mysql+pymysql://root#localhost:3306/db2'
}
db = SQLAlchemy()
class table1(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
.......
class table10(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
class table11(db.Model):
__bind_key__ = 'db2'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
......
class table20(db.Model):
__bind_key__ = 'db2'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
I want to use alembic autogenerate function to auto detecting and generating migrations for db 1 and db2 separately, but db.metadata will get all tables metadata, but how to just get bind db metadata?
Thanks #davidism help! I can use include_symbol to make it.
def include_symbol(tablename, schema):
return tablename in ('table1', 'table2'.......'table10') # for db1
 # return tablename not in ('table1', 'table2'.......'table10') # for db2
with connectable.connect() as connection:
context.configure(
connection=connection,
target_metadata=target_metadata,
include_symbol=include_symbol
)
You can't because that feature doesn't exist yet. Currently, there is one metadata instance for all models across all binds. As long as all the models have unique names, this isn't a huge problem.
When we apply this patch and make a new release, each bind will have its own metadata. You will then be able to access it with db.get_metadata(bind='db2').

Using SqlAlchemy Models in flask

I created some models using SqlAlchemy for setting up the database initially. Initially i parse some XML files and populate the database. This is a one time thing which needs to be done when i setup the app on server.
Base = declarative_base()
class Movie(Base):
__tablename__ = 'Movies'
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(80))
filename = Column(String(80), unique=True)
genre = Column(String(80))
language = Column(String(80))
year = Column(Integer)
description = Column(Text)
poster = Column(String)
def __init__(self, title, filename, genre, language, year, description, poster):
self.title = title
self.filename = filename
self.genre = genre
self.language = language
self.year = year
self.description = description
self.poster = poster
def __repr__(self):
return '<Movie (id=%d, title=%s, filename=%s, genre=%s, year=%s, description=%s, poster=%s)>' % (
self.id, self.title, self.filename, self.genre, self.year, self.description, self.poster )
......
Now i want to use the same models in the flask also for a REST api. But from what i have seen, first i need to create a db instance using the flask app - like this
app = Flask(__name__)
db = SQLAlchemy(app)
class Movie(db.Model):
.......
How does this workout? Since my models are inheriting from the Base class but for flask they need to inherit from the db.Model class.
you can simply use your models as they are, they do not "need" to inherit from db.Model, that is simply a convince to make flask integration easier
You can to create a module with the SQLAlchemy instance and use only the inheritance in the another's modules.
in database.py module:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
movieModel.py
from database import db
class MovieModel(db.Model):
__tablename__ = 'movie'
id = db.Column(db.Integer, primary_key=True)
imageModel.py
from database import db
class ImageModel(db.Model):
__tablename__ = 'image'
id = db.Column(db.Integer, primary_key=True)

Categories