SQLAlchemy and for some reason when i run my create_db.py only the migration table is created.
I tried it from python terminal with from modules import db,models then running db.create_all() but it still gives the same result.
this is my models.py.
from __init__ import db
from datetime import datetime
class Batch(db.Model):
__tablename__='batch'
batch_id = db.Column(db.String, primary_key=True)
#total = db.Column(db.Integer)
success = db.Column(db.Integer)
failure = db.Column(db.Integer)
folder = db.Column(db.String(15))
email = db.Column(db.String(20))
detail = db.relationship('Conversion', backref='details',lazy='dynamic')
platform = db.relationship('Platform', backref='pub_data', lazy = 'dynamic')
def __init__(self,batch_id,success,failure,folder,email):
self.batch_id = batch_id
self.success = success
self.failure = failure
self.folder = folder
self.email = email
class Conversion(db.Model):
__tablename__ = 'conversion'
id = db.Column(db.Integer, primary_key=True)
batch_id = db.Column(db.String,db.ForeignKey('batch.batch_id'))
file_names = db.Column(db.String)
status = db.Column(db.String(6))
error = db.Column(db.Text)
res_prop = db.Column(db.Integer)
def __init__(self,batch_id,file_names,status,res_prop,error=None):
self.batch_id = batch_id
self.file_names = file_names
self.status = status
self.error = error
self.res_prop = res_prop
class Platform(db.Model):
__tablename__ = 'platform'
id= db.Column(db.Integer,primary_key=True)
batch_id = db.Column(db.String, db.ForeignKey('batch.batch_id'))
title = db.Column(db.String)
pub_date = db.Column(db.DateTime)
def __init__(self,batch_id,title):
self.batch_id = batch_id
self.title = title
self.pub_date = datetime()
And here is my create_db.py
from modules import models
from modules import db
from migrate.versioning import api
from modules.default_config import SQLALCHEMY_DATABASE_URI , SQLALCHEMY_MIGRATE_REPO
import os.path
db.create_all()
db.session.commit()
if not os.path.exists(SQLALCHEMY_MIGRATE_REPO):
api.create(SQLALCHEMY_MIGRATE_REPO, 'database repository')
api.version_control(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
else:
api.version_control(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO, api.version(SQLALCHEMY_MIGRATE_REPO))
on changing
from __init__ import db
to
from modules import db
in models.py it worked.
when running flask application from outside package one needs to import everything from the package itself and not the individual modules.
Related
I am trying to create an API in Python that uses a Postgresql database. I am attempting a simple endpoint to pull to check to see if the database can connect and pull data. I am probably missing something simple and need someone to point it out. Below is my main.py file
import psycopg2
import model
import os
from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy
uname = os.environ['uname']
pas = os.environ['pas']
url = os.environ['url']
port = os.environ['port']
dbase = os.environ['dbase']
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2://' + uname + ':' + pas + '#' + url + ':' + port + '/' + dbase
db = SQLAlchemy(app)
#app.route('/test')
def test():
tst = model.Doc.query.filter_by(doc_num=1).first()
return jsonify(tst)
if __name__ == '__main__':
app.run()
I also have a model.py file where my database is modeled out.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Column, Integer, String, Date, ForeignKey
from flask_marshmallow import Marshmallow
app = Flask(__name__)
db = SQLAlchemy(app)
ma = Marshmallow(app)
class Aud(db.Model):
__tablename__ = 'aud'
__table_args__ = {'schema': 'cirsx'}
aud_num = Column(Integer, primary_key=True)
aud_name = Column(String, nullable=False, unique=True)
aud_desc = Column(String)
class AudSchema(ma.Schema):
class Meta:
fields = ('aud_num', 'aud_name', 'aud_desc')
class DocTyp(db.Model):
__tablename__ = 'doctyp'
__table_args__ = {'schema': 'cirsx'}
doctyp_num = Column(Integer, primary_key=True)
doctyp_name = Column(String, nullable=False, unique=True)
doctyp_desc = Column(String)
class DocTypSchema(ma.Schema):
class Meta:
fields = ('doctyp_num', 'doctyp_name', 'doctyp_desc')
class Doc(db.Model):
__tablename__ = 'doc'
__table_args__ = {'schema': 'cirsx'}
doc_num = Column(Integer, primary_key=True)
doctyp_num = Column(Integer, ForeignKey('doctyp_num'))
aud_num = Column(Integer, ForeignKey('aud_num'))
doc_path = Column(String, nullable=False)
title = Column(String, nullable=False)
author = Column(String)
keywords = Column(String)
pub_dt = Column(Date)
doc_abs = Column(String)
doc_txt = Column(String)
class DocSchema(ma.Schema):
class Meta:
fields = ('doc_num',
'doctyp_num',
'aud_num',
'doc_path',
'title',
'author',
'keywords',
'pub_dt',
'doc_abs',
'doc_txt')
aud_schema = AudSchema()
aud_schemas = AudSchema(many=True)
doctyp_schema = DocTypSchema()
doctyp_schemas = DocTypSchema(many=True)
doc_schema = DocSchema()
doc_schemas = DocSchema(many=True)
if __name__ == '__main__':
app.run()
Is there something that I am missing to why I am getting this error?
I have postgres db with some data, i can do everything i want until i add relation to Employee and EmployeeExperience, then a get an error lok like:
InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers. Triggering mapper: 'mapped class EmployeeExperience->employee_experience'. Original exception was: Mapper 'mapped class Employee->employee' has no property 'employee_experience'
I read a lot of tutorials and don't unerstand what i did wrong, any solution doesn't work for me, pls help, here is my code.
import psycopg2
import datetime
# <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
from flask import Flask
from flask_bcrypt import Bcrypt
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "postgres://postgres:postgres#localhost:5433/db_name"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy()
db.init_app(app)
flask_bcrypt = Bcrypt()
flask_bcrypt.init_app(app)
app.app_context().push()
# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< models
class Employee(db.Model):
__tablename__ = "employee"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
surname = db.Column(db.String(200))
first_name = db.Column(db.String(200))
birth_date = db.Column(db.Date)
email = db.Column(db.String(300), unique=True)
city = db.Column(db.String(200))
latitude = db.Column(db.Float)
longitude = db.Column(db.Float)
male = db.Column(db.Integer)
registered_on = db.Column(db.DateTime)
active = db.Column(db.Integer)
_password = db.Column(db.String(400))
employee_experience = db.relationship("EmployeeExperience", back_populates="employee")
class EmployeeExperience(db.Model):
__tablename__ = "employee_experience"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
position = db.Column(db.String(300))
company = db.Column(db.String(200))
city = db.Column(db.String(200))
description = db.Column(db.Text)
desc_raw = db.Column(db.Text)
employee_id = db.Column(db.Integer, db.ForeignKey('employee.id'))
employee = db.relationship("Employee", back_populates="employee_experience")
# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
emp = Employee.query.first()
'mapped class Employee->employee' has no property 'employee_experience'
The error cause is clearly stated. You have not defined the employe_experience attribute yet on your Employee model
I am trying to create a basic blog post website. Everything was going fine until i tried to run the app and it showed me the error:-
"Exception: Missing user_loader or request_loader"
but I have already created the user_loader. so I tried to find solutions and in the process I found that flask db migrate is not creating any table. so I searched online and found a solution to add all my tables in evn.py file in migration folder. I thought that was the problem and I tried to run the app again and this appeared again:-
"Exception: Missing user_loader or request_loader"
This is my __init__py file
# blogpost/__init__.py
import os
import secrets
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
app = Flask(__name__)
app.config['SECRET_KEY'] = secrets.token_hex(8)
# DATABASE CONFIGURATION #############
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
Migrate(app, db)
# LOGIN CONFIGURATION #################
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'users.login'
# IMPORTING BLUEPRINTS #################################
from blogpost.core.views import core
from blogpost.user.views import users
# BLUEPRINTS CONFIGURATION #################################
app.register_blueprint(core)
app.register_blueprint(users)
and this is my models.py file.
from blogpost import db, login_manager
from flask_login import UserMixin
from datetime import datetime
from werkzeug.security import check_password_hash, generate_password_hash
#login_manager.user_loader
def load_user(user_id):
return User.query.get(user_id)
fav_posts = db.Table('fav_posts',
db.Column('user_id', db.Integer, db.ForeignKey('users.id')),
db.Column('fav_posts_id', db.Integer, db.ForeignKey('posts.id')))
follows = db.Table('follows',
db.Column('user_id', db.Integer, db.ForeignKey('users.id')),
db.Column('follows', db.Integer, db.ForeignKey('users.id')))
fav_tags = db.Table('fav_tags',
db.Column('user_id', db.Integer, db.ForeignKey('users.id')),
db.Column('fav_tags_id', db.Integer, db.ForeignKey('tags.id')))
licked_posts = db.Table('licked_posts',
db.Column('post_id', db.Integer, db.ForeignKey('posts.id')),
db.Column('user_id', db.Integer, db.ForeignKey('users.id')))
tags_included = db.Table('tags_included',
db.Column('post_id', db.Integer, db.ForeignKey('posts.id')),
db.Column('user_id', db.Integer, db.ForeignKey('tags.id')))
class User(db.Model, UserMixin):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), unique=True, index=True)
email = db.Column(db.String, unique=True, index=True)
dob = db.Column(db.Date)
password_hash = db.Column(db.String)
account_created = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
profile_image = db.Column(db.String)
is_verified = db.Column(db.Boolean, default=False)
posts = db.relationship('Post', backref='author', lazy=True)
favorite_posts = db.relationship('Post', secondary=fav_posts, backref=db.backref('fav_by', lazy='dynamic'))
followers = db.relationship('User', secondary=follows, backref=db.backref('following', lazy='dynamic'))
favorite_tags = db.relationship('Tag', secondary=fav_tags, backref=db.backref('users', lazy='dynamic'))
def __init__(self, email, password, username, dob):
self.email = email
self.username = username
self.dob = dob
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
class Post(db.Model):
__tablename__ = 'posts'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String)
body = db.Column(db.Text)
date_created = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
likes = db.relationship('User', secondary=licked_posts, backref=db.backref('licked_by', lazy='dynamic'))
tags_includes = db.relationship('Tag', secondary=tags_included,
backref=db.backref('post_including_tag', lazy='dynamic'))
def __init__(self, title, body):
self.title = title
self.body = body
class Tag(db.Model):
__tablename__ = 'tags'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
def __init__(self, name):
self.name = name
can anyone one tell me what should I do to solve this and more importantly what is the cause because I have done same in my previous project but this never happened.
UPDATE:-
I've solved this problem by creating my user_loader inside my init file after the login_manager.login_view = 'users.login' file. I imported the User model after this line and then created the user_loader.
so my guess is that the problem is that flask is not able to find the "models.py" file. if anyone can explain the problem accurately or have a better solution you're most welcome (^-^)
here is another work i did for practice and it worked fine.
#puppycompanyblog/__init__.py
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
app = Flask(__name__)
app.config['SECRET_KEY'] = 'mysecretkey'
#DATABASE SETUP##########################
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir,'data.sqlite')
app.config['SQLALCHEMY_TRACK_MODIFICATION'] = False
db = SQLAlchemy(app)
Migrate(app,db)
#########################################
#LOGIN CONFIGURATIONS####################
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'users.login'
#########################################
from puppycompanyblog.core.views import core
from puppycompanyblog.users.views import users
from puppycompanyblog.blog_posts.views import blog_posts
from puppycompanyblog.error_pages.handlers import error_pages
app.register_blueprint(core)
app.register_blueprint(users)
app.register_blueprint(blog_posts)
app.register_blueprint(error_pages)
and
# puppycompanyblog/models.py
from puppycompanyblog import db, login_manager
from werkzeug.security import check_password_hash, generate_password_hash
from flask_login import UserMixin
from datetime import datetime
#login_manager.user_loader
def load_user(user_id):
return User.query.get(user_id)
class User(db.Model, UserMixin):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
profile_image = db.Column(db.String(64), nullable=False, default='default_profile.png')
email = db.Column(db.String(64), unique=True, index=True)
username = db.Column(db.String(64), unique=True, index=True)
password_hash = db.Column(db.String(128))
posts = db.relationship('BlogPost', backref='author', lazy=True)
def __init__(self, email, username, password, ):
self.email = email
self.username = username
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
def __repr__(self):
return f"username: {self.username}"
class BlogPost(db.Model):
users = db.relationship(User)
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
title = db.Column(db.String(140), nullable=False)
text = db.Column(db.Text, nullable=False)
def __init__(self, title, text, user_id):
self.title = title
self.text = text
self.user_id = user_id
def __repr__(self):
return f"Post ID: {self.id} -- Date: {self.date} --- {self.title}"
The reason why the user_loader function isn't found is because you are not importing the module in which it is defined. You put it in models.py, so you need to import this module somewhere in the area where you define your application, so that the handler is registered with the Flask-Login extension. You'll also need to import this file so that Flask-SQLAlchemy registers your models.
Based on the code that you posted, you could add import models at the bottom of blogpost/__init__.py and I think that should do it (it needs to be at the bottom to prevent circular imports).
I'm trying to get a list of all the relationships for a table with Flask SQLAlchemy, but don't see any option, just on how to create relationships.
Does anyone know how I can do this? Any help is much appreciated.
Here is a simple example of 3 models. How can I get a list of the two relationships from the Member model?
from flask_sqlalchemy import SQLAlchemy
from flask import Flask
import os
from flask_login import UserMixin
app = Flask(__name__)
file_path = os.path.abspath(os.getcwd()) + "\database.db"
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///" + file_path
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["SECRET_KEY"] = "my secret!"
db = SQLAlchemy(app)
class Member(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(40), unique = True)
hobbies = db.relationship("Hobbies", backref="member", lazy="dynamic")
friends = db.relationship("Friends", backref="member", lazy="dynamic")
def __init__(self, name):
self.name = name
def __repr__(self):
return "<Member {}>".format(self.id)
class Hobbies(db.Model):
id = db.Column(db.Integer, primary_key = True)
hobby = db.Column(db.String(40))
user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
def __init__(self, hobby, user_id):
self.hobby = hobby
self.user_id = user_id
def __repr__(self):
return "<Hobbies {}>".format(self.id)
class Friends(db.Model):
id = db.Column(db.Integer, primary_key = True)
friend = db.Column(db.String(40))
user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
def __init__(self, friend, user_id):
self.friend = friend
self.user_id = user_id
def __repr__(self):
return "<Friends {}>".format(self.id)
from sqlalchemy.inspection import inspect
relations = inspect(Member).relationships.items()
I am trying to insert new data to my database but my web application returns this error.
My codes are as follows:
models.py
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
...
class Patient(db.Model):
__tablename__ = "patients"
id = db.Column(db.Integer, primary_key=True)
lname = db.Column(db.String, nullable=False)
fname = db.Column(db.String, nullable=False)
mname = db.Column(db.String, nullable=True)
address = db.Column(db.String, nullable=False)
birthdate = db.Column(db.Date, nullable=False)
date_modified = db.Column(db.DateTime, nullable=False)
modified_by = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False)
date_created = db.Column(db.DateTime, nullable=False)
created_by = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False)
def __init__(self, fname, mname, lname):
self.fname = fname
self.mname = mname
self.lname = lname
application.py
import os
from flask import *
from flask_session import Session
from sqlalchemy import *
from sqlalchemy.orm import scoped_session, sessionmaker
from models import *
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = os.getenv("DATABASE_URL")
# Check for environment variable
if not os.getenv("DATABASE_URL"):
raise RuntimeError("DATABASE_URL is not set")
app.secret_key = '######'
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db.init_app(app)
engine = create_engine(os.getenv("DATABASE_URL"))
db = scoped_session(sessionmaker(bind=engine))
...
#app.route("/submitpatient", methods=["POST"])
def submitpatient():
fname = request.form.get("fname")
mname = request.form.get("mname")
lname = request.form.get("lname")
patient = Patient(fname=fname, mname=mname, lname=lname)
db.session.add(patient)
db.session.commit()
return redirect(url_for('index'))
I'm new to python and I have been trying to find the error in my code for hours but I can't seem to find anything that would help me.
I guess the problem that u missed to create a constructor "Session" after using it,
The code will be:
# create a configured "Session" class
Session = scoped_session(sessionmaker(bind=engine))
#app.route("/submitpatient", methods=["POST"])
def submitpatient():
fname = request.form.get("fname")
mname = request.form.get("mname")
lname = request.form.get("lname")
patient = Patient(fname=fname, mname=mname, lname=lname)
#create a Session
session = Session()
session.add(patient)
session.commit()
return redirect(url_for('index'))
for more information, see this
What if you just add and commit as follows,
db.add(patient)
db.commit()
Use Session object with SQLAlchemy's declarative way
I know this answer is not exactly related to the questioner's scenario but a similar issue can arise if you are using flask-security's user model with sqlalchemy in a declarative way.
In this case, your user_datastore should be as below:
user_datastore = SQLAlchemySessionUserDatastore(db_session, User, Role) not SQLAlchemyUserDatastore
For more explanation:
database.py
import importlib
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine("sqlite:///crm.sqlite3")
db_session = scoped_session(sessionmaker(autocommit=False,
autoflush=False,
bind=engine))
Base = declarative_base()
Base.query = db_session.query_property()
def create_db(all_microservices_names = []):
_ = importlib.import_module("database.models.all_models")
Base.metadata.create_all(bind=engine)
all_models.py
import sqlalchemy as sa
from database.database import Base
from flask_security import RoleMixin, UserMixin
class User(Base, UserMixin):
id = sa.Column(sa.Integer(), primary_key=True)
public_id = sa.Column(sa.String(length=255), unique=True, nullable=False)
username = sa.Column(sa.String(20), unique=True, nullable=False)
#...
datastore.py
from flask_security import SQLAlchemySessionUserDatastore
from database.database import db_session
from database.models.user_models import User, Role
user_datastore = SQLAlchemySessionUserDatastore(db_session, User, Role)
app.py will contain the initialization of these elements including login_manager and attach it to the Flask app.