sqlalchemy does not initialize the database - python

I have created a models.py file describing my schema. I am using the code below to create the DB and initialize it with the model.py schema. When I call the create_app function a new sqlite file gets create but it is empty. It is not picking up the schema from my models.py file.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy_utils.functions import database_exists
db = SQLAlchemy()
DB_NAME = "database.db"
def create_app():
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{DB_NAME}'
if not database_exists(app.config['SQLALCHEMY_DATABASE_URI']):
db.init_app(app)
db.create_all(app=app)
print(f'Created Database Successfully!!')
return app
models.py
from .main import db
from flask_login import UserMixin
from sqlalchemy.sql import func
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(150), unique=True)
password = db.Column(db.String(150))
first_name = db.Column(db.String(150))

happened to me with missing init.py file in the package, maybe thats the case

After I imported the models file first, the DB was created sucessfully.

Related

SQLAlchemy not creating table in database

I am creating a website using a flask with a signup form that saves the signup info in a database. however, it is not creating any tables in the database.
my init.py file looks like this:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from os import path
#intitialising databas: works correctly
db = SQLAlchemy()
DB_NAME = 'database.db'
def create_app():
app = Flask(__name__)
app.config['SECRET_KEY'] = 'shhh dont tell'
app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{DB_NAME}'
db.init_app(app)
#importing our blue prints
from .views import views
from .auth import auth
app.register_blueprint(views,urlprefix='/')
app.register_blueprint(auth,urlprefix='/')
from .models import User
create_database(app)
return app
#database creates successfully
def create_database(app):
if not path.exists('website/source' + DB_NAME):
db.create_all(app=app)
print('Created Database')
and my models.py looks like:
from enum import unique
from sqlalchemy import true
from website.source import db
from flask_login import UserMixin
#schema of table according to mega tut and sqlalchemy
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
firstName = db.Column(db.String(150))
lastName = db.Column(db.String(150))
userName = db.Column(db.String(150), unique=True)
password = db.Column(db.String(150))
I am not sure why this is happing. when I run the app on the flask and do my sign up form and click the submit button I get the error
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) table user has no column named userName
I have looked at multiple youtube tutorials and I seem to be doing everything correctly. any help would be appreciated
thanks

Sql alchemy sqlalchemy.exc.NoReferencedTableError not creating tables

I'm working with flask and trying to learn sqlalchemy, I have a database where I added a third table to make a new feature, but the entire project stopped working, it says:
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'url_reference.folder_rel' could not find table 'reffolders' with which to generate a foreign key to target column 'id'
this is the dbs.py
from . import db
from flask_login import UserMixin
from sqlalchemy.sql import func
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(200), unique=True)
user_password = db.Column(db.String(150))
user_name = db.Column(db.String(400))
user_refs = db.relationship("RefFolders")
class RefFolders(db.Model):
id = db.Column(db.Integer, primary_key=True)
folder_title = db.Column(db.String(1000))
date_added = db.Column(db.DateTime(timezone=True), default=func.now())
user_rel = db.Column(db.Integer, db.ForeignKey("user.id"))
url_rel = db.relationship("UrlReference")
class UrlReference(db.Model):
id = db.Column(db.Integer, primary_key=True)
ref_title = db.Column(db.String(1000))
ref_url = db.Column(db.String(30000))
date_added = db.Column(db.DateTime(timezone=True), default=func.now())
folder_rel = db.Column(db.Integer, db.ForeignKey("reffolders.id"))
this is where I make the database in the __init__.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from os import path
from flask_login import LoginManager
db = SQLAlchemy()
DB_NAME = "database.db"
def app():
app = Flask(__name__)
app.config['SECRET_KEY'] = '<here is the key in my code>'
app.config['SQLALCHEMY_DATABASE_URI'] = f"sqlite:///{DB_NAME}"
db.init_app(app)
# making the blueprints usable
from .views import views
from .auth import auth
app.register_blueprint(views, url_prefix="/")
app.register_blueprint(auth, url_prefix="/")
from .dbs import User
from .dbs import UrlReference
from .dbs import RefFolders
db_create(app)
# Login manager
login_manager= LoginManager()
login_manager.login_view = 'views.home'
login_manager.init_app(app)
# Searching and loading user
#login_manager.user_loader
def load_user(id):
return User.query.get(int(id))
return app
def db_create(app):
if not path.exists("project/" + DB_NAME):
db.create_all(app=app)
I don't know what happened, maybe a problem with having a double foreign key?
I think flask or its extension guesses the table name you want, like CamelCase --> camel_case.
So in this case the tablename is probably ref_folders. You might want to just use tablename to set the table name yourself although I think their default is a good convention.
As a side note I would recommend using _id for your ids otherwise things might get pretty confusing between object relations and actual ids, ie. use user_id instead of user_rel in RefFolders.
SEE:
https://flask-sqlalchemy.palletsprojects.com/en/2.x/models/#declaring-models
Some parts that are required in SQLAlchemy are optional in
Flask-SQLAlchemy. For instance the table name is automatically set for
you unless overridden. It’s derived from the class name converted to
lowercase and with “CamelCase” converted to “camel_case”. To override
the table name, set the __tablename__ class attribute.

Flask migration is not applying on all tables

i have a project where i create four tables (users,products, agents, customer) when i do migration with:
flask db init,
flask db migrate,
flask db upgrade,
only users and products get migrated
here it is the structure of my project:
my code for user model is:
from main.extensions import db
from main.shared.base_model import BaseModel, HasCreatedAt,
HasUpdatedAt
class User(BaseModel, HasCreatedAt, HasUpdatedAt):
tablename = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String, unique=True, nullable=False)
password = db.Column(db.String, nullable=False)
phone = db.Column(db.Integer)
my code for every module starting by agent model:
from main.extensions import db
class Agent(db.Model):
__tablename__ = 'agents'
id = db.Column(db.Integer, primary_key=True)
picture = db.Column(db.String)
def __init__(self,email, password, phone, picture):
self.email = email
self.password=password
self.phone=phone
self.picture=picture
and for the model in customer is:
from main.modules.user.models import User
from main.extensions import db
class Customer(User):
__tablename__ = 'customers'
approved = db.Column(db.Boolean)
picture = db.Column(db.String)
def __init__(self, email, password, phone, picture, approved):
self.approved = approved
self.picture = picture
User.__init__(self,email,password,phone)
and finnaly the products model has:
from main.extensions import db
from main.shared.base_model import BaseModel, HasCreatedAt, HasUpdatedAt
class Product(BaseModel, HasCreatedAt, HasUpdatedAt):
__tablename__ = 'products'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
the settings.py contains the following code:
and this init files for every model contains this code:
for the user __init.py:
from main.modules.users.api import blueprint as api
for the customer __init.py:
from main.modules.customer.api import blueprint as api
for the agent__init.py:
from main.modules.agent.api import blueprint as api
for the prodcut__init.py:
from main.modules.product.api import blueprint as api
import os
class DevSettings(Settings):
DEBUG = True
basedir = os.path.abspath(os.path.dirname(__file__))
SQLALCHEMY_DATABASE_URI="sqlite:///" + os.path.join(basedir, "data.sqlite")
SQLALCHEMY_TRACK_MODIFICATIONS=False
and the extension.py contains:
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
migrate = Migrate()
and the app.py contains this:
from flask import Flask, Blueprint
from main.extensions import db, migrate
from main.modules import product, agent, customer, user
from main.settings import DevSettings
MODULES = [ agent, customer,product, user]
main = Blueprint('main', __name__)
def create_app(settings=DevSettings):
app = Flask(__name__)
# Utiliser la configuration (settings).
app.config.from_object(settings)
app.config['SECRET_KEY'] = 'mysecretkey'
# On initialise les libraries Python.
# Init SQLAlchemy.
db.init_app(app)
# Init Migrate.
migrate.init_app(app, db)
app.register_blueprint(main)
register_modules(app)
return app
def register_modules(app):
for m in MODULES:
if hasattr(m, 'api'):
app.register_blueprint(m.api)

Flask application factory pattern init empty database, not my model on ubuntu

I want to create a flask application using the application factory pattern, I want to separate my logic and my models. The server starts without errors, but after I migrate my database it creates an empty db.
I'm currently using ubuntu, in windows it creates the db properly.
__init__.py:
from flask import Flask, request, jsonify
from .extensions import db
from flask_migrate import Migrate
migrate = Migrate()
def create_app():
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db'
from .models import File
db.init_app(app)
migrate.init_app(app, db)
return app
The models.py:
from .extensions import db
class File(db.Model):
id = db.Column(db.Integer, primary_key=True)
audio_path = db.Column(db.String(255), unique=True)
original_txt = db.Column(db.String(255), unique=True)
corrected_txt = db.Column(db.String(255), unique=True)
creation_date = db.Column(db.DateTime)
def __repr__(self):
return 'File %r' % self.audio_path
extensions.py is where I define my SQLAlchemy db:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
Why is it not creating the database from my model?
this just works for me:
you need to declare db = SQLAlchemy() inside the models.py file, not in the extensions file, and then in the init.py file import db from models, init the db class by: db.init_app(app). and migrate.init_app(app, db).

Error "NameError: name 'UsersAdmin' is not defined" when moved all classes to another file

Short story. I took this example:https://github.com/MrJoes/Flask-Admin/tree/master/examples/sqla i played with it and everything was fine until i decided what i want to split app.py(main file) to two parts. In main file app.py i will keep views and in another models.py i will keep all classes. Both files are in same folder.
Issue. I get error Error when running my app.py file:
"NameError: name 'UserAdmin' is not defined"
This is part from app.py file where i try to call Class UserAdmin from models.py file:
import os
import os.path as op
from flask import Flask, render_template, request, redirect, url_for, abort, session, flash
from flask_sqlalchemy import SQLAlchemy, Model
from flask_login import UserMixin, session, LoginManager, login_user, login_required, logout_user
from flask_bcrypt import Bcrypt,check_password_hash,generate_password_hash
from models import *
from flask_admin import Admin, BaseView, expose
app = Flask(__name__)
app.config['SECRET_KEY'] = '123456790'
app.config['DATABASE_FILE'] = 'db.sqlite'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE']
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
admin = Admin(app, name='Admin Site', template_mode='bootstrap3')
# Add views. This is where it fails
admin.add_view(UserAdmin(User, db.session))
models.py file where is described UserAdmin part:
from wtforms import validators
from app import db, app, url_for, admin
from flask_admin.contrib import sqla
from flask_admin.contrib.sqla import filters, ModelView
from flask_login import UserMixin
...
# Create models
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(100))
last_name = db.Column(db.String(100))
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
# Required for administrative interface. For python 3 please use __str__ instead.
def __str__(self):
return self.username
class UserInfo(db.Model):
id = db.Column(db.Integer, primary_key=True)
key = db.Column(db.String(64), nullable=False)
value = db.Column(db.String(64))
user_id = db.Column(db.Integer(), db.ForeignKey(User.id))
user = db.relationship(User, backref='info')
def __str__(self):
return '%s - %s' % (self.key, self.value)
class UserAdmin(sqla.ModelView):
inline_models = (UserInfo,)
...
If someone could point me what i am doing wrong there it would be very nice.
Thanks

Categories