pallets-eco / flask-sqlalchemy Goto Github PK
View Code? Open in Web Editor NEWAdds SQLAlchemy support to Flask
Home Page: https://flask-sqlalchemy.palletsprojects.com
License: BSD 3-Clause "New" or "Revised" License
Adds SQLAlchemy support to Flask
Home Page: https://flask-sqlalchemy.palletsprojects.com
License: BSD 3-Clause "New" or "Revised" License
Things like apply_driver_hacks are very useful to subclass and should be documented.
I never remember to call .items, and I was just reminded of this when getting a new developer spun up. Instead of:
for obj in MyModel.query.paginate(1).items: pass
I expect:
for obj in MyModel.query.paginate(1): pass
... because SQLAlchemy's query API does this everywhere. This fails, because a Pagination instance is not iterable.
I don't know if this is a config issue or a bug at this point.
Flast-SQLAlchemy is used as part of mead project.
** My setup is in a virtual environment:
** python version
(mead_dev)seth@dharma:~/Code/python/mead_dev/mead$ python -V
Python 2.7.2+
** Please take a look at the stack dump below. Object name seem not to be defined.
Looked @ the code and don't have much context.
_EngineConnector.get_uri() does some binding, which fails to be defined properly and is not 'sane'.
Hence an invalid uri is returned. Also digging further it seems that the binding to a db-engine is not defined. So maybe this is a config issues?
** Maybe you can shed some light on this?
[stack trace](mead_dev)seth@dharma:~/Code/python/mead_dev/mead$ ./run_server.py
Traceback (most recent call last):
File "./run_server.py", line 4, in <module>
from mead import app
File "/home/seth/Code/python/mead_dev/mead/mead/**init**.py", line 66, in <module>
import mead.core.views.content
File "/home/seth/Code/python/mead_dev/mead/mead/core/views/content.py", line 10, in <module>
from available import defaults
File "/home/seth/Code/python/mead_dev/mead/mead/core/views/available.py", line 22, in <module>
defaults.update(dict(pages = Page.query.all()))
File "/home/seth/Code/python/mead_dev/local/lib/python2.7/site-packages/Flask_SQLAlchemy-0.15-py2.7.egg/flaskext/sqlalchemy.py", line 386, in **get**
return type.query_class(mapper, session=self.sa.session())
File "/home/seth/Code/python/mead_dev/local/lib/python2.7/site-packages/SQLAlchemy-0.7.3-py2.7.egg/sqlalchemy/orm/scoping.py", line 53, in **call**
return self.registry()
File "/home/seth/Code/python/mead_dev/local/lib/python2.7/site-packages/SQLAlchemy-0.7.3-py2.7.egg/sqlalchemy/util/_collections.py", line 877, in __call__
val = self.registry.value = self.createfunc()
File "/home/seth/Code/python/mead_dev/local/lib/python2.7/site-packages/Flask_SQLAlchemy-0.15-py2.7.egg/flaskext/sqlalchemy.py", line 191, in **init**
bind=db.engine,
File "/home/seth/Code/python/mead_dev/local/lib/python2.7/site-packages/Flask_SQLAlchemy-0.15-py2.7.egg/flaskext/sqlalchemy.py", line 719, in engine
return self.get_engine(self.get_app())
File "/home/seth/Code/python/mead_dev/local/lib/python2.7/site-packages/Flask_SQLAlchemy-0.15-py2.7.egg/flaskext/sqlalchemy.py", line 736, in get_engine
return connector.get_engine()
File "/home/seth/Code/python/mead_dev/local/lib/python2.7/site-packages/Flask_SQLAlchemy-0.15-py2.7.egg/flaskext/sqlalchemy.py", line 428, in get_engine
self._sa.apply_driver_hacks(self._app, info, options)
File "/home/seth/Code/python/mead_dev/local/lib/python2.7/site-packages/Flask_SQLAlchemy-0.15-py2.7.egg/flaskext/sqlalchemy.py", line 679, in apply_driver_hacks
if info.drivername == 'mysql':
AttributeError: 'NoneType' object has no attribute 'drivername'
The method get_or_404(ident) is wrongly used in the docs http://packages.python.org/Flask-SQLAlchemy/queries.html#queries-in-views as the ident parameter was added. This should be corrected with an added explanation for the ident paramter.
I suppose there might be multiple occurrences of out-of-date docs. This should also be looked into.
Currently lazy=dynamic relationships return a sqlalchemy query and not a Flask-SQLAlchemy query. The methods on SQLAlchemy() should inject that automatically with the query_class
parameter.
That parameter is also supported for backref
and relationship
, even though the docs do not mention that.
I just subclassed db.Query and was surprised that my custom query property didn't have get_or_404().
I wonder if db.Query should really refer to the flaskext.sqlalchemy.BaseQuery class. I realize that this is not without it's problems, since that would essentially be breaking the promise that you can access the SQLAlchemy identifiers via db.*, and Query would be the lone exception; but it seems to be that use-case wise, it's much more common that people really want to subclass BaseQuery; it should be rare that soneone would insist on working with the plain SQLAlchemy Query class.
I try to bind the application after my model declaration to the SQLAlchemy object with the function db.init_app(app), but the db engine is always None.
Hi,
First, thank you for developing Flask, I'm having a lot of fun playing with it.
I see that the doc mentions a 0.10 version, and so does the setup.py file. However, the corresponding tag and pypi packages seems to be missing. Is this intended ?
I have an implementation of Mozilla's password policy in Python that creates an HMAC key, uses b64 encoded version of it within bcrypt to create an encrypted password.
When I create one of these manually and insert it in to SQLite directly, it all works fine and is as expected.
When I insert this in to the database using a model and db.session the value in SQLite is not the value that was inserted.
i.e.
db.session.add(User("kura", "bcrypt$2a$12$7kmx7ZdtXwUSsfdfBxp/ouhGnWhPIylCZUYhifnIaMcyM4hkNg9Jq$2012-02-14", "[email protected]", "Kura"))
db.session.commit()
When I query that result, instead of getting the value I inserted I get
bcrypt$2a$12$RGkcKVIM6.Crv.ZIzVn5EuxN6OYEHic2zO8IBhCHVev0WT7F0klKu$2012-02-14
Querying SQLite directly using the Linux binary shows that the second (incorrect) value is the one stored.
If I change that value manually using the SQLite binary and then requery from Python it is correct.
Any ideas why this would be the case?
SQL Alchemy events are registered by calling the listen function with a class, an event name and a function. By returning a partial, you make it difficult to attach listeners. I suppose you could work around this issue by calling type(db.session()), however a decent amount of debugging is required to figure out why things don't work in the first place.
A simple solution is to create a singalling_session_maker function that takes the same arguments as signalling_session, then define _SignallingSession inside this function with a reduced init function, and return it. Then you can just call that factory inside of scoped_session().
Hello,
please take a look at https://gist.github.com/1643718
Please execute this script and watch how it adds an string to user_id where a int is needed and then successfully commit the object to sqlite3.
I use flask-sqlalchemy 0.15, flask 0.6 (debian squeezy flask-0.6-1), libsqlite3-0 3.7.3 (debian squeeze libsqlite3-0 3.7.3-1)
cheers,
robin
I would prefer not to couple my modeling code to my web application. My preferred technique is to create a metadata in the same module as my model definitions, passing that later to table definitions. This lets me use the same module definitions in external scripts without a lot of overhead.
It only happens, as the article says, if the server has been inactive for about 8 hours. Since my site is part of an office intranet, this happens daily.
Wondering how to go about fixing this with Flask-SQLAlchemy.
More info here: http://rapd.wordpress.com/2008/03/02/sqlalchemy-sqlerror-operationalerror-2006-mysql-server-has-gone-away/
Hi,
I've just setup a new virtualenv and pulled the latest Flask-SQLAlchemy module from pip but I'm having issues when trying to configure a one-to-one relationship between two objects like so:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
db = SQLAlchemy(app)
class Parent(db.Model):
__tablename__ = 'parents'
id = db.Column(db.Integer, primary_key=True)
child_id = db.Column(db.Integer, db.ForeignKey("children.id"))
child = db.relationship("Child", backref=db.backref("parent", uselist=False))
class Child(db.Model):
__tablename__ = 'children'
id = db.Column(db.Integer, primary_key=True)
db.create_all()
parent = Parent()
child = Child()
This code errors with the following error:
ArgumentError: Could not determine join condition between parent/child tables on relationship Parent.child. Specify a 'primaryjoin' expression. If 'secondary' is present, 'secondaryjoin' is needed as well.
According to the SQLAlchemy documentation (http://docs.sqlalchemy.org/en/latest/orm/relationships.html#one-to-one) the above should work without issue.
It is worth noting that I have a previous virtual-environment with Flask-SQLAlchemy before the namespace was changed from flaskext.sqlalchemy
to flask_sqlalchemy
and the above code runs fine using that.
Cheers,
David.
Hello,
I'm trying to complete the sample application as described on http://packages.python.org/Flask-SQLAlchemy/ . I'm trying to query the users I created as described in the code section after "And how do you get the data back? Easy as pie:" and here is what I get:
(veFlask)remy@remy-virtual-machine:~/Projects/Hello World$ python
Python 2.6.6 (r266:84292, Sep 15 2010, 15:52:39)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from dbtest import User
>>> users = User.query.all()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'all'
>>> print User.query
None
I've followed the previous sample application steps to the point. I'm using Flask 0.6 and Flask-SQLAlchemy 0.9.1.
there is default for mysql driver in flask-sqlalchemy
options.setdefault('pool_recycle', 7200)
Most servers will timeout client connection in 1 hour IMO it's better to use this as a default value and let people change it to longer times when appropriate.
(....there is another caveat right now - if your mysql server got restarted there is nothing that would catch exception and try to reconnect to serve current request, I wonder if that exception would be possible to catch in lib, not inside of the application code)
It seems the before_models_committed is never sent.
Looking in depth in this piece of code:
class _SignalTrackingMapperExtension(MapperExtension):
def after_delete(self, mapper, connection, instance):
return self._record(mapper, instance, 'delete')
def after_insert(self, mapper, connection, instance):
return self._record(mapper, instance, 'insert')
def after_update(self, mapper, connection, instance):
return self._record(mapper, instance, 'update')
def _record(self, mapper, model, operation):
pk = tuple(mapper.primary_key_from_instance(model))
orm.object_session(model)._model_changes[pk] = (model, operation)
return EXT_CONTINUE
class _SignallingSessionExtension(SessionExtension):
def before_commit(self, session):
d = session._model_changes
if d:
before_models_committed.send(session.app, changes=d.values())
return EXT_CONTINUE
def after_commit(self, session):
d = session._model_changes
if d:
models_committed.send(session.app, changes=d.values())
d.clear()
return EXT_CONTINUE
def after_rollback(self, session):
session._model_changes.clear()
return EXT_CONTINUE
the problem seems like this:
but i can't figure out how this happen
Right now the declarative base initialization does not pass a custom mapper, instead the mapper is "monkey" patched on.
Example:
http://friendpaste.com/2EBQ2hT2PLXMWmMiq4LeKI
Why do I get a different behavior from this flask extension than from regular sqlalchemy?
With Flask 0.6 you can now use signals. These could be tied to specific events in SQLAlchemy model lifecyle, using the MapperExtension (http://www.sqlalchemy.org/docs/reference/orm/interfaces.html#sqlalchemy.orm.interfaces.MapperExtension). Example events could be "after_delete", "before_insert" etc.
When querying using a mapped class or instance, the query_class
is flaskext.sqlalchemy.BaseQuery
and i get the expected exception with the following:
user.query.paginate()
TypeError: paginate() takes at least 2 arguments (1 given)
But when using a relationship configured on a class or instance query_class
is None and paginate() not available.
user.roles.paginate()
AttributeError: 'AppenderQuery' object has no attribute 'paginate'
Flask-SQLAlchemy is big enough that it should get a CHANGES and setup.cfg file for improved release management.
Please release a new version of Flask-SQLAlchemy to pypi that contains the versioned_listeners keyword argument when creating an SQLAlchemy db object.
We have master and slave replication for our database and just want the ability to read from the database of our choice. Will Flask-SQLAlchmey support for multiple databases? If not any work arounds?
Would be awesome to have query abilities like django
User.query.filter_by(id=1).using("slave")
Since most of the projects using sqlalchemy uses mysql / postgres there is a good chance of using transactions. Having a commit_on_success decorator can save a try except block in the view functions. Here is a rough draft of the decorator I wrote.
https://gist.github.com/14d12595f3dfa307a354
Just wondering if its a good idea to get the db object from the function object. (line # 11)?
I tried the VersionedMeta example in the docs and it doesn't work.
Using: SQLAlchemy 0.6.8; Flask-SQLAlchemy 0.15
history_meta.py is the unchanged version from SQLAlchemy 0.6.8 examples.
Code:
from flask import Flask
from flaskext.sqlalchemy import SQLAlchemy
from history_meta import VersionedMeta, VersionedListener
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
db = SQLAlchemy(app, session_extensions=[VersionedListener()])
class User(db.Model):
__metaclass__ = VersionedMeta
username = db.Column(db.String(80), unique=True)
pw_hash = db.Column(db.String(80))
if __name__ == '__main__':
app.run()
Error:
Traceback (most recent call last):
File "flask_sqla_versiontest.py", line 13, in <module>
class User(db.Model):
TypeError: Error when calling the metaclass bases
metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
What is wrong?
class User(db.Model):
__abstract__ = True
id = Column(Integer, primary_key=True)
class Manager(User):
name = Column(String)
This code must declare only one table manager
, with two fields id
and name
. But Flask-SQLAlchemy doesn't generate __tablename__
for class Manager, because it doesn't have a primary key field. So, accessing Manager.__tablename__
results in user
, which obviously not what I want.
When I have a model like this:
class Category(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False, unique=True)
count = db.Column(db.Integer, nullable=False, default=0)
class Article(db.Model):
id = db.Column(db.Integer, primary_key=True)
category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
content = db.Column(db.Text, nullable=False)
category = db.relationship('Category', backref='articles')
and want to update count
on Category
for every new Article
, I would do:
from sqlalchemy.orm.attributes import get_history
def update_category_count(sender, changes):
for model, change in changes:
if isinstance(model, Article):
if change == 'new':
model.category.count += 1
elif change == 'deleted':
model.category.count -= 1
elif change == 'updated':
# Need to know old category before updating `Category.count`.
added, unchanged, deleted = get_history(model, 'category')
if added and deleted:
deleted[0].count -= 1
added[0].count += 1
db.session.commit()
models_committed.connect(update_category_count)
This won't going to work for several reason:
db.session.commit()
here will raise InvalidRequestError
.get_history
is not able to retrieve older state, presumably because the model is already committed and object no longer being marked as dirty.model.category.count
won't issue an UPDATE
for some reason. From my understanding, it is not possible to modify flush plan at this point.No changes are sent to update_category_count
when changing to before_models_committed
. update_category_count
need to be called by before_flush
in order to modify flush plan:
from flask.signals import Namespace
from sqlalchemy.orm.interfaces import SessionExtension, EXT_CONTINUE
signals = Namespace()
before_flush = signals.signal('models-before-flush')
class FlushSignalExtension(SessionExtension):
def before_flush(self, session, flush_context, instances):
before_flush.send(session.app, session=session, instances=instances)
return EXT_CONTINUE
from itertools import ifilter
from sqlalchemy.orm.attributes import get_history
def update_category_count(sender, session, instances):
predicate = lambda s: isinstance(s, Article)
for article in ifilter(predicate, session.new):
article.category.count += 1
for article in ifilter(predicate, session.deleted):
article.category.count -= 1
for article in ifilter(predicate, session.dirty):
added, unchanged, deleted = get_history(article, 'category')
if added and deleted:
deleted[0].count -= 1
added[0].count += 1
before_flush.connect(update_category_count)
This works, category is properly UPDATE
d. So I think it would be useful if Flask has before_flush
and after_flush
signals built-in.
(I have not tested the code above, but they're reproduced from an actual case of a production code I'm not allowed to post part of it anywhere. Sorry.)
Currently queries depend on the request context. Is this really necessary? investigate.
It would be nice to be able to modify the query property without having to monkey-patch. Here's an example of how I'm going about it now: http://paste.pocoo.org/show/265847/
(sqlalchemy.py)
def apply_driver_hacks(self, app, info, options):
if info.drivername == 'mysql':
This fails to recognize URIs like 'mysql+pymsql://...'
I guess it should check 'contains mysql' or even a regex check like '^mysql+'.
Thanks.
The documentation mentions adding an info={'bind_key': 'users'}
parameter to a Table to bind it. However, this parameter is thrown away:
def _make_table(db):
def _make_table(*args, **kwargs):
if len(args) > 1 and isinstance(args[1], db.Column):
args = (args[0], db.metadata) + args[1:]
info = kwargs.pop('info', None) or {}
info.setdefault('bind_key', None)
return sqlalchemy.Table(*args, **kwargs)
return _make_table
info
above is never re-added to kwargs. A simple fix:
def _make_table(db):
def _make_table(*args, **kwargs):
if len(args) > 1 and isinstance(args[1], db.Column):
args = (args[0], db.metadata) + args[1:]
info = kwargs.pop('info', None) or {}
info.setdefault('bind_key', None)
kwargs['info'] = info
return sqlalchemy.Table(*args, **kwargs)
return _make_table
For applications needing to use this functionality now, a workaround is to set the info
attribute right after you create the object.
The assertion in the following code fails:
from flask import Flask
from flaskext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
db.create_all()
test = User(username='test')
db.session.add(test)
assert len(db.session.query(User).all()) == 1
The equivalent code written using only SQLAlchemy works:
from sqlalchemy import create_engine, Column, String, Integer
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine('sqlite:///:memory:')
Base = declarative_base()
session = scoped_session(sessionmaker(bind=engine))()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(80), unique=True)
Base.metadata.create_all(bind=engine)
test = User(username='test')
session.add(test)
assert len(session.query(User).all()) == 1
If I do something like:
lat = db.Column(db.Float(precision=16, scale=6), nullable=False)
and then I use MySQL's SHOW CREATE TABLE tablename .. I get the following:
lat
float NOT NULL,
Which shows that the precision and scale parameters are ineffective.
Right now something depends on blinker, so either the testsuite or Flask-SQLAlchemy itself is doing something wrong.
Right now, there's no simple way to provide a base Model object because everything is done on the make_declarative_base
function, the options is to override and redo what's done on that function. Could we provide a different Model when creating the SQLAlchemy object? or provide the model as a class attribute(since I'm already subclassing it)?
Flask-sqlalchemy version: 0.15
SQLAlchemy version: 0.7.3
Problem:
db = SQLAlchemy()
db.init_app(myapp)
db.reflect(app=myapp)
File "/home/user/Envs/myenv/lib/python2.7/site-packages/flaskext/sqlalchemy.py", line 811, in reflect
self._execute_for_all_tables(app, bind, 'reflect')
File "/home/user/Envs/myenv/lib/python2.7/site-packages/flaskext/sqlalchemy.py", line 787, in _execute_for_all_tables
op(bind=self.get_engine(app, bind), tables=tables)
TypeError: reflect() got an unexpected keyword argument 'tables'
It seems like the _execute_for_all_tables method is not suitable for the reflect
method.
as discussed on IRC:
Jython 2.5.3b1 (2.5:5fa0a5810b25, Feb 22 2012, 12:39:02)
[OpenJDK 64-Bit Server VM (Oracle Corporation)] on java1.7.0_03-icedtea
Type "help", "copyright", "credits" or "license" for more information.
>>> from flaskext.sqlalchemy import SQLAlchemy
>>> SQLAlchemy()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/fnd/jython/Lib/site-packages/flaskext/sqlalchemy.py", line 606, in __init__
_include_sqlalchemy(self)
File "/home/fnd/jython/Lib/site-packages/flaskext/sqlalchemy.py", line 81, in _include_sqlalchemy
setattr(obj, key, getattr(module, key))
AttributeError: 'module' object has no attribute 'sys'
(tested with Jython v2.5.2 and v2.5.3b1)
Wrapping that line in a try ... except: pass
seems to work fine (debugging shows that "sys" is the only key to throw that error).
some more data based on our IRC conversation:
Jython 2.5.3b1 (2.5:5fa0a5810b25, Feb 22 2012, 12:39:02)
[OpenJDK 64-Bit Server VM (Oracle Corporation)] on java1.7.0_03-icedtea
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlalchemy
>>> sqlalchemy.__all__
['BLOB', 'BOOLEAN', 'BigInteger', 'Binary', 'Boolean', 'CHAR', 'CLOB',
'CheckConstraint', 'Column', 'ColumnDefault', 'Constraint', 'DATE',
'DATETIME', 'DDL', 'DECIMAL', 'Date', 'DateTime', 'DefaultClause', 'Enum',
'FLOAT', 'FetchedValue', 'Float', 'ForeignKey', 'ForeignKeyConstraint',
'INT', 'INTEGER', 'Index', 'Integer', 'Interval', 'LargeBinary',
'MetaData', 'NCHAR', 'NUMERIC', 'NVARCHAR', 'Numeric', 'PassiveDefault',
'PickleType', 'PrimaryKeyConstraint', 'REAL', 'SMALLINT', 'Sequence',
'SmallInteger', 'String', 'TEXT', 'TIME', 'TIMESTAMP', 'Table', 'Text',
'ThreadLocalMetaData', 'Time', 'TypeDecorator', 'Unicode', 'UnicodeText',
'UniqueConstraint', 'VARCHAR', 'alias', 'and_', 'asc', 'between',
'bindparam', 'case', 'cast', 'collate', 'create_engine', 'delete', 'desc',
'distinct', 'engine_from_config', 'except_', 'except_all', 'exists',
'extract', 'func', 'insert', 'intersect', 'intersect_all', 'join',
'literal', 'literal_column', 'modifier', 'not_', 'null', 'or_',
'outerjoin', 'outparam', 'over', 'select', 'subquery', 'sys', 'text',
'tuple_', 'type_coerce', 'union', 'union_all', 'update']
Support multiple engines.
Perhaps I'm misunderstanding the intended use of SQLAlchemy.init_app, but it appears that it doesn't assign it's arg (a Flask application object) to its instance.
This tripped me up as I was creating my SQLALchemy instance in a separate module from my application and tests and binding it to the Flask application object later. I had thought from the documentation that this meant I should use the init_app method, but doing so just threw errors that the SQLAlchemy instance wasn't bound to an application object.
Manually assigning the application object to the SQLAlchemy.app attribute works around the problem.
I'd love to see the repo URL be updated to point to:
hi, Armin,
I met some problem that wired me the whole day. I'm using flask/flask-sqlalchemy/postgresql, and I want to do this:
published_sites = msg_published.query
.filter( and_(*filter_clause) )
.group_by( msg_published.site_id )
.order_by( order_clause )
.paginate( page_no, per_page, error_out = False )
but in mysql, it is OK, and in postgresql it is wrong and ask for the other fields besides site_id either in a group by clause or in a aggregation function, I know that postgresql is stricter on SQL than mysql , so I must select the site_id in the query object of msg_published, but in pure sqlalchemy I can do like this:
published_sites = session.query( msg_published.site_id )
.filter( and_(*filter_clause) )
.group_by( msg_published.site_id )
.order_by( order_clause )
.paginate( page_no, per_page, error_out = False )
and in flask-sqlalchemy, how to get it work?
i think, in the init_app() of class SQLAlchemy, add the following clause would be better:
self.app = app
because, if some create db as following:
db = SQLAlchemy()
db.init_app()
then, db.app is not set, db.get_app would use ctx.app
While Flask itself seem to have quite a heavy emphasis on splitting ones' application into several module, it does not seem like flask-sqlalchemy has any support for that.
My gut feeling is that I'm missing something obvious, but I might be mistaken. Either way, it should be documented.
Flask-SQLAlchemy is big enough for a multi-page documentation. Should also include patterns and tips.
The link to http://sqlalchemy.org
needs to be http://www.sqlalchemy.org
.
I found no mention in the docs about the proper way to structure models in a Flask app. Right now I have this:
# app.py
db = SQLAlchemy(app)
and:
# models.py
from app import db
class MyModel(db.Model):
# ...
But this means I have a circular dependency once I try to do:
# app.py
from models import MyModel
It's worth mentioning how this should be done in the docs.
I already use a Pagination class with SQLAlchemy and werkzeug.
The implementation is similar, but more complete in some way.
http://paste.pocoo.org/show/222332/
Main differences:
Flask-SQLAlchemy automatically generates a value for __tablename__
; doing so breaks single table inheritance, which requires that the __tablename__
attribute be undefined.
http://www.sqlalchemy.org/docs/orm/extensions/declarative.html#single-table-inheritance
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.