Flask SQLAlchemy db.create_all() not creating database - python

I can't seem to figure out why my call to db.create_all() is not working.
I have an app package with following init:
from flask import Flask
from config import config
from flask.ext.sqlalchemy import SQLAlchemy
# create the database object
db = SQLAlchemy()
# this function is the application factory
def create_app(environment):
app = Flask(__name__)
app.config.from_object(config[environment])
db.init_app(app)
from bp_root import bp_root
from bp_aws import bp_aws
app.register_blueprint(bp_root, url_prefix='/')
app.register_blueprint(bp_aws, url_prefix='/aws')
return app
Then I have models.py inside the app package:
from datetime import datetime
from . import db
class MyTestClass(db.Model):
__tablename__ = 'mytesttable'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(64), nullable=False, unique=True, index=True)
username = db.Column(db.String(64), nullable=False, unique=True, index=True)
is_admin = db.Column(db.Boolean)
password_hash = db.Column(db.String(128))
location = db.Column(db.String(64))
member_since = db.Column(db.DateTime, default=datetime.utcnow)
bio = db.Column(db.Text())
def __init__(self, email, username):
self.email = email
self.username = username
def __repr__(self):
return '<User %r>' % self.username
app.config contains, among other things, the following:
'SQLALCHEMY_DATABASE_URL': 'sqlite:////Users/xxxxx/projects/yyyyy/data-dev.sqlite'
Then if I fire up my interactive shell, you can see objects exist appropriately and call to db.create_all() appears to work, but results in no database creation:
$ ./manage.py shell
>>> from app import db
>>> from app import models
>>> app
<Flask 'app'>
>>> db
<SQLAlchemy engine='sqlite://'>
>>> models
<module 'app.models' from '/Users/xxxxx/projects/yyyyy/app/models.py'>
>>> dir(models)
['MyTestClass', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'datetime', 'db']
>>> db.create_all()
>>>
Any thoughts on why the database isn't getting created?

The setting should be SQLALCHEMY_DATABASE_URI, not URL. You can see that the db doesn't have the right uri when you ran this line:
>>> db
<SQLAlchemy engine='sqlite://'>
It shows that Flask-SQLAlchemy defaulted to an in-memory sqlite database. Change the setting and it will work.
As of Flask-SQLAlchemy 3, it will raise an error instead of using a default.
RuntimeError: Either 'SQLALCHEMY_DATABASE_URI' or 'SQLALCHEMY_BINDS' must be set

Related

Can't create the initial database with Flask-SQLAlchemy?

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:password#localhost/database'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
def __repr__(self):
return '<User %r>' % self.username
When I try to run it
>> from app.py import db
>> db.create_all()
Above is the complete error message
I have found in the Task Manager, the postgresql service is on.
The database password is correct and I can't find where the error is.
My computer is Win10 and I installed postgresql using the official installer
replace the word database with the name of your database
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:password#localhost/database'
by default, your database name is likely 'postgres', you also need to provide your port number, default is 5432.
Try using the following:
app.config['SQLALCHEMY_DATABASE_URI'] = "postgresql://postgres:password#localhost:5432/postgres"

How to retrieve a row from SQLalchemy with flask

I am learning how to use SQLalchemy and databases in general with flask. I am following a tutorial and it uses the below classes and files.
https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-iv-database
To show an inserted row in the database, the tutorial uses the following:
from app.models import User
>>> u = User(username='susan', email='susan#example.com')
>>> u
<User susan>
My problem is that I can not display the same output. I mean when I code the the statement, I get an error
from app.models import User
ImportError: No module named app.models
Please let me know how to adapt the posted code so I can retrieve data from database
Folder Structure:
d:\xxx\xxx\db1\app\models
d:\xxx\xxx\db1\__init__
d:\xxx\xxx\db1\config
** init **:
from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
from app import routes, models
config:
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config(object):
# ...
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
'sqlite:///' + os.path.join(basedir, 'app.db')
SQLALCHEMY_TRACK_MODIFICATIONS = False
models:
from app import db
from app.models import User
class User(db.Model):
id = db.Column(db.Integer, primaty_key=True)
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
password_hash = db.Column(db.String(128))
def __repr__(self):
return '<User {}>'.format(self.username)
You cannot import User on the same module where models is declared, so I don't think If you need that second line in models.py, Try commenting and see what happens
from app import db
from app.models import User ## I think the problems is
class User(db.Model):
id = db.Column(db.Integer, primaty_key=True)
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
password_hash = db.Column(db.String(128))
def __repr__(self):
return '<User {}>'.format(self.username)

Flask Shell Commands not working

I'm new to python and flask and currently working on the Flask Mega-Tutorial, however: I'm stuck getting flask shell to recognize my custom symbols/commands.
When I try to access the model User as a symbol by typing flask shell in my virtual environment, I get NameError: name 'User' is not defined.
User should return: <class 'application.models.User'>, but shows the error instead.
What I don't understand is that the app symbol seems to work fine and returns <Flask 'application'> as it should.
What am I doing wrong here? Something with the imports?
I did some research: this looks like my problem but does not use the app.sell_context_processor decorator.
I tried also variations of my code: both changing import names from app to application as I changed these from the default in the tutorial and using user instead of User (lower vs. uppercase), but nothing seems to work.
Please help me fix this!
Error
(venv) MBP:books mbpp$ flask shell
Python 3.6.5 (default, Mar 30 2018, 06:42:10)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
App: application
Instance: /Users/mbpp/Sites/books/instance
>>> app
<Flask 'application'>
>>> User
Traceback (most recent call last):
File "<console>", line 1, in <module>
NameError: name 'User' is not defined
My code from application.py
from application import app, db
from application.models import User, Book, State, Course, BookTitle, Author
#app.shell_context_processor
def make_shell_context():
return {'db': db, 'User': User, 'State': State, 'BookTitle': BookTitle, 'Author': Author}
and from __init__.py
from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
# initiate the Flask app
app = Flask(__name__)
# use the config.py file for configuration
app.config.from_object(Config)
# use SQLAlchemy for database management
db = SQLAlchemy(app)
# use Flask-Migrate extension for database migration management
migrate = Migrate(app, db)
# use Flask-Login extension for login form
login = LoginManager(app)
login.login_view = 'login'
from application import routes, models
and from models.py (I'm building a website where users can sell books)
from application import db, login
from datetime import datetime
from werkzeug.security import generate_password_hash,
check_password_hash
from flask_login import UserMixin
# create a table to store users
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key = True)
username = db.Column(db.String(64), index = True, unique = True)
email = db.Column(db.String(120), index = True, unique = True)
password_hash = db.Column(db.String(128))
phone = db.Column(db.String(64))
books = db.relationship('Book', backref='seller_name', lazy='dynamic')
def __repr__(self):
return '<User: {}>'.format(self.username)
# create a password hash
def set_password(self, password):
self.password_hash = generate_password_hash(password)
# check the password hash against a user given password
def check_password(self, password):
return check_password_hash(self.password_hash, password)
# create a table to store information on a book for sale
class Book(db.Model):
id = db.Column(db.Integer, primary_key = True)
course_id = db.Column(db.Integer, db.ForeignKey('course.id'))
title = db.Column(db.Integer, db.ForeignKey('booktitle.id'))
author = db.Column(db.Integer, db.ForeignKey('author.id'))
price = db.Column(db.Integer)
isbn = db.Column(db.String(64), index = True)
state_id = db.Column(db.Integer, db.ForeignKey('state.id'))
state_description = db.Column(db.String(256))
seller_id = db.Column(db.Integer, db.ForeignKey('user.id'))
creation_timestamp = db.Column(db.DateTime, index = True, default = datetime.utcnow)
def __repr__(self):
return '<Book: {}>'.format(self.title)
# create a table to store different states books can be in
class State(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(128), index = True)
books = db.relationship('Book', backref='state', lazy='dynamic')
def __repr__(self):
return '<State: {}>'.format(self.name)
# create a table to store courses
class Course(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(128), index = True)
year = db.Column(db.Integer, index = True)
books = db.relationship('Book', backref='course', lazy='dynamic')
def __repr__(self):
return '<Course: {}>'.format(self.name)
# create a table to store booktitles
class BookTitle(db.Model):
id = db.Column(db.Integer, primary_key = True)
title = db.Column(db.String(128), index = True)
books = db.relationship('Book', backref='book_title', lazy='dynamic')
def __repr__(self):
return '<Book title: {}>'.format(self.title)
# create a table to store authors
class Author(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(128), index = True)
books = db.relationship('Book', backref='author_name', lazy='dynamic')
def __repr__(self):
return '<Author: {}>'.format(self.name)
# user loader for Flask-Login extension, gets users ID
#login.user_loader
def load_user(id):
return User.query.get(int(id))
Thanks a lot to Miguel, the writer of the FLASK Mega Tutorial (go check that out) wo solved my problem!
As he pointed out in a comment below my question: you cannot have a module and a package with the same name. So no application folder and application.py at the same time.
Solution:
I changed my 'application.py into 'theapp.py' and now flask shell works like a charm! I did not need to change anything in my files, apart from running export FLASK_APP=theapp.py in the terminal.
Flask needs to be told how to import it, by setting the
FLASK_APP:(venv) $ export FLASK_APP=microblog.py
If you are using Microsoft Windows, use set instead of export in the command above.

SQLAlchemy don't create tables if using Marshmallow

I'm trying to create a project using Flask, Flask-SQLAlchemy, flask-restplus and marshmallow (tried with flask-marshmallow too), but the integration of these tools does not work very well.
Everytime I include some new lib, a new error occur.
I already give up to use migrations with Flask-SQLAlchemy because for some reason, this thing don't work. But now, the problem is with marshmallow.
I'm trying to make with modules and I think this is the part of the problem (all examples of Flask-SQLAlchmey, flask-restplus, flask-marshmallow, etc put everything in a single file)
This is my app.py:
from flask import Flask, Blueprint
import settings
from api import api
from database import init_database, reset_database
app = Flask(__name__)
def configure_app(flask_app):
flask_app.config['SERVER_NAME'] = settings.SERVER_ADDRESS
flask_app.secret_key = settings.SECRET_KEY
def initialize_app(flask_app):
configure_app(flask_app)
blueprint = Blueprint('api', __name__, url_prefix=settings.URL_PREFIX)
api.init_app(blueprint)
# api.add_namespace(auth_login_namespace)
flask_app.register_blueprint(blueprint)
init_database(flask_app)
if settings.DEBUG:
reset_database(flask_app)
def main():
initialize_app(app)
app.run(debug=settings.DEBUG)
if __name__ == '__main__':
main()
api/__init__.py:
import settings
from flask_restplus import Api
api = Api(
version='1.0',
title='Test',
description='Some description'
)
#api.errorhandler
def default_error_handler(e):
message = 'An unhandled exception occurred.'
if not settings.DEBUG:
return {'message': message}, 500
database/__init__.py:
from flask_sqlalchemy import SQLAlchemy
import settings
db = SQLAlchemy()
def init_database(flask_app):
flask_app.config['SQLALCHEMY_DATABASE_URI'] = settings.DATABASE_URI
flask_app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
global db # I really don't like this! :(
db = SQLAlchemy(flask_app)
def reset_database(flask_app):
from database.models import User
db.drop_all()
db.create_all()
db.session.add(User(username='admin', email='abc#def.com', name='admin', password='123', admin=True)
db.session.commit()
I have my app, with only one model until now:
database/models/User.py:
from marshmallow import Schema, fields
from sqlalchemy import func
from database import db
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, index=True)
email = db.Column(db.String(120), unique=True, index=True)
name = db.Column(db.String(200), nullable=False)
password = db.Column(db.String(200), nullable=False)
admin = db.Column(db.Boolean, nullable=False, default=False)
created_on = db.Column(db.DateTime, nullable=False, server_default=func.now())
class UserSchema(Schema):
id = fields.Int(dump_only=True)
username = fields.Str()
email = fields.Email()
name = fields.Str()
password = fields.Str()
admin = fields.Bool()
created_on = fields.DateTime()
now, if I use the following code (this code is called everytime my app start on debug mode, on function reset_database, in file database/__init__.py):
db.drop_all()
db.create_all()
db.session.add(User(username='admin', email='abc#def.com', name='admin', password='123', admin=True)
db.session.commit()
the User table is not created, and the admin is not inserted on table, because the table don't exist (db.create_all() don't create anything).
sqlite3.OperationalError: no such table: user.
For some reason, if I remove the class UserSchema (on database/models/User.py), the db.create_all() function create the table).
Got working right now:
on database/__init__.py, altered the init_database function to:
def init_database(flask_app):
flask_app.config['SQLALCHEMY_DATABASE_URI'] = settings.DATABASE_URI
flask_app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(flask_app)
and in database/reset_database.py:
def reset_database(flask_app):
with flask_app.app_context():
from database.models.user_module import User
db.drop_all()
db.create_all()
db.session.add(User(username='admin', email='abc#def.com', name='admin', password='123', admin=True))
db.session.commit()
The problems was the init_app, use the app_context, and I'm importing the wrong User module (tks Fian)

python flask sqlalchemy, i can'trun my db_create.py

Ame getting this error of TypeError: init() takes exactly 1 argument (5 given)...where have i gone wrong?? any help i will appreciate ,thanks
thats my db_create.py file
from app import db
from models import post
db.create_all()
db.session.add(post("Good", "i\m good","yes","hae"))
db.session.add(post("Good", "hahaha"))
db.session.add(post("Good", "you"))
db.session.add(post("Good", "hahaha"))
my model.py file is
from app import db
class post(db.Model):
# table name
__tablename__ = "signup"
#columns names
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String, nullable=False)
email= db.Column(db.String, nullable=False)
password = db.Column(db.String, nullable=False)
confirm= db.Column(db.String, nullable=False)
def __init__(self, username, email, password, confirm):
self.username = username
self.email = email
self.pasword = password
self.confirm = confirm
def __repr__(self,*args, **kwargs):
return '<username {}'.format(self.username), 'email{}'.format(self.email),'password{}'.format(self.password)
this is my init
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.secret_key = "my previous"
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///signup.db'
db = SQLAlchemy(app)
from app import views
You don't need the __init__ method in your post model. Just use the __init__ method inherited from db.Model and you should be fine.
But then I believe you'd need to modify your db_create.py a bit:
For example:
db.session.add(post(username="User", email="user#email.com", password="password", confirm="Yes"))
Also you need to remember to commit your changes:
db.session.commit()

Categories