The two modules server.py and models.py are in the same directory. I import the models before running the create_all but the User table is never created. I have also tried changing import models to from models import User with the same result. Please help me understand what is going on here.
Server.py:
from flask import Flask
from fileserver.filebutler import butler
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.register_blueprint(butler)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://working_url'
db = SQLAlchemy(app)
def initialize_db():
import models
db.create_all()
if __name__ == '__main__':
initialize_db()
app.run(debug=True)
models.py:
from sqlalchemy import Column, Integer, String
from downloadr import db
class User(db.Model):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50), unique=True)
email = Column(String(120), unique=True)
def __init__(self, name=None, email=None):
self.name = name
self.email = email
def __repr__(self):
return '<User %r>' % (self.name)
Try:
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), unique=True)
email = db.Column(db.String(120), unique=True)
Use:
from models import *
It works fine in my case (i'm not using a function to init though, just 2 lines of code in the if clause).
Related
I am creating my first larger Python Flask app and one of the modules I will be using is Flask_User. To make all a bit more manageable I wanted to impost a blueprint and factory app.
The structure is simple:
app.py
config.py
auth/
__init__.py
models.py
So the goal is to have all authentication stuff in auth section. However, it comes down to where to initialize UserManager not to have errors, circular references, etc.
user_manager = UserManager(app, db, User)
How code looks like - app.py
from flask import Flask
# Configuration
from config import Config, HomeDevelopmentConfig
# Extensions
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
# INITIATE DB
db = SQLAlchemy()
migrate = Migrate() # this will run SQLAlchemy as well
from flask_user import UserManager
from auth.models import User
user_manager = UserManager()
# APPLICATION FACTORY
def create_app(config_class=Config):
# Create app object
app = Flask(__name__)
# Load configuration
app.config.from_object(config_class)
# Register extensions
db.init_app(app)
migrate.init_app(app, db)
user_manager = UserManager(app, db, User) # !!! this will not work - circular reference to User as User needs db
# Close session with DB at the app shut down
#app.teardown_request
def shutdown_session(exception=None):
db.session.remove()
with app.app_context():
# Register blueprints
# Main flask app
from main import bp_main
app.register_blueprint(bp_main)
# Authentication (flask-user)
from auth import bp_auth
app.register_blueprint(bp_auth)
return app
# RUN APPLICATION
if __name__ == '__main__':
app = create_app(HomeDevelopmentConfig)
app.run()
models.py (should contain data structure for authentication)
from app import db
from flask_user import UserMixin #, UserManager
class User(db.Model, UserMixin):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(100), nullable=False, unique=True)
password = db.Column(db.String(255), nullable=False, server_default='')
first_name = db.Column(db.String(100), nullable=False, server_default='')
last_name = db.Column(db.String(100), nullable=False, server_default='')
email_confirmed_at = db.Column(db.DateTime())
active = db.Column('is_active', db.Boolean(), nullable=False, server_default='0')
# Define the relationship to Role via UserRoles
roles = db.relationship('Role', secondary='user_roles')
class Role(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(50), unique=True)
class UserRoles(db.Model, UserMixin):
__tablename__ = 'user_roles'
id = db.Column(db.Integer(), primary_key=True)
user_id = db.Column(db.Integer(), db.ForeignKey('users.id', ondelete='CASCADE'))
role_id = db.Column(db.Integer(), db.ForeignKey('roles.id', ondelete='CASCADE'))
and finally init.py for authentication:
from flask import blueprints
bp_auth = blueprints.Blueprint('auth', __name__)
from auth import models
Looks like mission impossible, but maybe you have some good hints. What works is to put all the code into app.py, but that make
I'm trying to create a function that can be scheduled to delete all rows within an SQLAlchemy model.
I'm trying to use apscheduler to accomplish this task. But I keep getting an error that says:
sqlalchemy.orm.exc.UnmappedInstanceError: Class 'flask_sqlalchemy.model.DefaultMeta' is
not mapped; was a class (app.models.User) supplied where an instance was required?
Am I missing something?
Here is my app/__init__.py:
from flask import Flask
from flask_login import LoginManager
from flask_sqlalchemy import SQLAlchemy
from config import Config
app = Flask(__name__)
db = SQLAlchemy()
login = LoginManager()
app.config.from_object(Config)
db.init_app(app)
login.init_app(app)
login.login_view = 'login'
from app import routes, models
and here is my manage.py:
from apscheduler.schedulers.background import BackgroundScheduler
from app import app, db
from flask_migrate import Migrate
from flask_script import Manager
from app.models import User
manager = Manager(app)
migrate = Migrate(app, db)
def clear_data():
db.session.delete(User)
print("Deleted User table!")
#manager.command
def run():
scheduler = BackgroundScheduler()
scheduler.add_job(clear_data, trigger='interval', seconds=5)
scheduler.start()
app.run(debug=True)
if __name__ == '__main__':
manager.run()
Also, here's my model:
from app import db, login
from datetime import datetime
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True, unique=True)
api_token = db.Column(db.String(50), unique=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))
todos = db.relationship('Todo', backref='owner', lazy='dynamic')
def __repr__(self):
return '<models.py {}>'.format(self.username)
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
#login.user_loader
def load_user(id):
return User.query.get(int(id))
class Todo(db.Model):
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.String(140))
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
def __repr__(self):
return '<Todo {}>'.format(self.body)
As your error indicated, it is expecting an instances of an object, and you instead passed it a class. I think the issue is the first line in the clear_data function:
db.session.delete(User)
It was expecting an instances of a User record to delete, and doesn't know how to delete the whole table using just the model.
Check out this answer on how to delete all rows in a table. There are a few ways to do this, but this may be the least change for you:
db.session.query(User).delete()
In this case you are adding the step of SELECTing all the records in the table User maps to, then deleting them.
P.S.: as mentioned in the linked answer, you need to .commit() your session, otherwise it won't stick, and will rollback after you close the connection.
db.session.commit()
Code snippet:
db.session.query(model_name).delete()
db.session.commit()
I am trying to filter data by username in Python and sql alchemy but somehow the filter is not working., i am able to filter by ID and add users., in below code, i just showed the method for filter by username. not sure what wrong i am doing
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
import os
app = Flask(__name__)
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir,
'datas.sqlite')
db = SQLAlchemy(app)
ma = Marshmallow(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
class UserSchema(ma.Schema):
class Meta:
# Fields to expose
fields = ('username', 'email')
user_schema = UserSchema()
users_schema = UserSchema(many=True)
#endpointtogetuserdetailbyusername
#app.route("/username/<username>",methods=["GET"])
def user_detailbyusername(username):
user=User.query.filter(User.username=='Tim')
# i tried user=User.query.filter_by(User.username=='Tim') but no luck
return user_schema.jsonify(user)
if __name__ == '__main__':
app.run(debug=True)
I think you should add some method to really get back the records, something like User.query.filter(User.username=='Tim').all() or User.query.filter(User.username=='Tim').first(), as can be seen in the examples at http://flask-sqlalchemy.pocoo.org/2.3/queries/#querying-records
I am following this tutorial https://www.youtube.com/watch?v=kuyrL6krkwA. I have modified the db, table, and columns names for my app. Everything else is identical to tutorial. The error occurs (10 mins into tutorial) where he enters python shell and runs the following commands:
from models import User # my app uses 'User' not 'BlogPost'
users = User.query.all()
The Python Shell Script returns error message below:
sqlalchemy.exc.OperationalError: (OperationalError) no such
column:users.id u'SELECT users.id AS users_id, users.name AS
users_name, users.zipcode AS users_zipcode, users.inter1 AS
users_inter1, users.inter2 AS users_inter2, users.inter3 AS
users_inter3 \nFROM users' ()
The three files I am using are (App.py, models.py, db_create.py)
App.py
from flask import Flask, render_template, request
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///mfiyzc.db'
db = SQLAlchemy(app)
if __name__ == "__main__":
app.run(debug = True)
models.py
from app import db
class User(db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
zipcode = db.Column(db.Integer, nullable=False)
inter1 = db.Column(db.String, nullable=False)
inter2 = db.Column(db.String, nullable=False)
inter3 = db.Column(db.String, nullable=False)
def __init__(self, name, zipcode, inter1, inter2, inter3):
self.name = name
self.zipcode = zipcode
self.inter1 = inter1
self.inter2 = inter2
self.inter3 = inter3
def __repr__(self):
return '<title {}'.format(self.title)
db_create.py
from app import db
from models import User
db.create_all()
db.session.add(User("Jane Parker", 11104, "ice skating", "dancing", "reading"))
db.session.add(User("Bob Smith", 11104, "boxing", "cars", "beers"))
db.session.commit()
You need to run db_create.py ie :
python db_create.py
or
from models import User
db.create_all()
You are trying to query the table before it has been created.
I had the wrong field name (since I copied from the tutorial)
incorrect:
def __repr__(self):
return '<title {}'.format(self.title)
correct:
def __repr__(self):
return '<name {}'.format(self.name)
I have a Flask app that is using Flask-SQLAlchemy. In my unit tests, I initialise the app and the DB, then call db.create_all() and for some reason it looks like it's not picking up any of my models so isn't creating any tables.
I'm using both __tablename__ and __bind_key__ in my models as I have two databases.
My config:
SQLALCHEMY_DATABASE_URI = 'sqlite://'
SQLALCHEMY_BINDS = {
'db1': SQLALCHEMY_DATABASE_URI,
'db2': SQLALCHEMY_DATABASE_URI
}
Cut down version of my setUp() method in my unit tests:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
class APITestCase(unittest.TestCase):
app = Flask(__name__)
db = SQLAlchemy(app)
db.create_all()
Here's an example of two of my models, one from each bind type:
class Contact(db.Model):
__tablename__ = 'contact'
__bind_key__ = 'db1'
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(255))
last_name = db.Column(db.String(255))
...
def __init__(first_name, last_name):
self.first_name = first_name
self.last_name = last_name
...
class BaseUser(db.Model):
__tablename__ = 'User__GeneralUser'
__bind_key__ = 'db2'
id = db.Column(db.Integer, primary_key=True)
username = db.Column('Username', db.String(100))
first_name = db.Column('FirstName', db.String(100))
last_name = db.Column('Surname', db.String(100))
...
def __init__(username, first_name, last_name):
self.username = username
self.first_name = first_name
self.last_name = last_name
...
Have I missed something glaringly obvious? How does Flask-SQLAlchemy know where to look for my models to create the associated tables?
In your unit tests you shouldn't create a new instance of the SQLAlchemy object ('db'), you should import the instance from which your models descend:
models.py:
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Contact(db.Model):
...
tests.py:
from models import db
from flask import Flask
import unittest
class TestExample(unittest.TestCase):
def setUp(self):
self.app = Flask(__name__)
db.init_app(self.app)
with self.app.app_context():
db.create_all()
your SQLALCHEMY_DATABASE_URI is wrong, read here how to configuration your engine Sqlite database http://docs.sqlalchemy.org/en/rel_0_9/core/engines.html#sqlite
if you never experience, see this repo and apply to your apps :)
https://github.com/Fird0s/Banda-Maps/blob/master/models.py