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
Related
I am trying to implement a restful API with Flask using flask-restful, flask-sqlalchemy and flask-marshmallow. I am aware there are many questions about this issue but I still can't figure it out.
Solutions like using strict=True in marshmallow schemas or adding .data to user_schema.dump(result) don't let me see my result in the response body.
Here is my code :
# User.py file
from flask import jsonify, request
from flask_restful import Resource
from src import db
from src.models.user import User
from src.validation import UserSchema
class Users(Resource):
def get(self):
try:
data = request.get_json()
user = User.query.filter_by(email=data['email']).first()
user_schema = UserSchema()
result = user_schema.dump(user)
return jsonify(result)
except:
return jsonify({'error_message': 'User not found'})
def post(self):
try:
data = request.get_json()
user = User(data["firstName"], data["lastName"],
data["email"], data["password"])
db.session.add(user)
db.session.commit()
user_schema = UserSchema()
result = user_schema.dump(user)
return result
except:
return jsonify({'error_message': 'User already exists in database'})
The init.py file :
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_restful import Api
from flask_marshmallow import Marshmallow
app = Flask(__name__)
app.config["DEBUG"] = True
app.config["SQLALCHEMY_ECHO"] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = "postgresql:///gauss"
ma = Marshmallow(app)
api = Api(app)
db = SQLAlchemy(app)
from src import routes
The validation.py file :
from src import ma
from src.models.user import User
class UserSchema(ma.SQLAlchemySchema):
class Meta:
model = User
And the User.py schema for the database :
from src import db
from datetime import datetime
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
firstName = db.Column(db.String(20))
lastName = db.Column(db.String(20))
email = db.Column(db.String(50), unique=True, nullable=False)
password = db.Column(db.String(), nullable=False)
createdAt = db.Column(db.DateTime, default=datetime.utcnow)
def __init__(self, firstName, lastName, email, password):
self.firstName = firstName
self.lastName = lastName
self.email = email
self.password = password
I've been looking for solutions for a few days now and it seems that marshmallow returning empty json occures mostly when querying with the .all() method for instance, because marshmallow .dump() method misses the Many=True configuration.
I'm probably missing something but I can't wrap my head around it. Any help appreciated !
i had the same problem, the solution to my problem was to change UserSchema(ma.SQLAlchemySchema): to UserSchema(ma.SQLAlchemyAutoSchema):
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 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)
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).