diff -Nru flask-sqlalchemy-2.2/CHANGES flask-sqlalchemy-2.1/CHANGES
--- flask-sqlalchemy-2.2/CHANGES 2017-02-27 15:20:34.000000000 +0000
+++ flask-sqlalchemy-2.1/CHANGES 2015-10-23 09:49:12.000000000 +0000
@@ -1,32 +1,13 @@
Changelog
=========
-Version 2.2
------------
-
-Released on February 27, 2017, codename Dubnium
+Here you can see the full list of changes between each Flask-SQLAlchemy
+release.
-- Minimum SQLAlchemy version is 0.8 due to use of ``sqlalchemy.inspect``.
-- Added support for custom ``query_class`` and ``model_class`` as args
- to the ``SQLAlchemy`` constructor. (`#328`_)
-- Allow listening to SQLAlchemy events on ``db.session``. (`#364`_)
-- Allow ``__bind_key__`` on abstract models. (`#373`_)
-- Allow ``SQLALCHEMY_ECHO`` to be a string. (`#409`_)
-- Warn when ``SQLALCHEMY_DATABASE_URI`` is not set. (`#443`_)
-- Don't let pagination generate invalid page numbers. (`#460`_)
-- Drop support of Flask < 0.10. This means the db session is always tied to
- the app context and its teardown event. (`#461`_)
-- Tablename generation logic no longer accesses class properties unless they
- are ``declared_attr``. (`#467`_)
+Version 3.0
+-----------
-.. _#328: https://github.com/mitsuhiko/flask-sqlalchemy/pull/328
-.. _#364: https://github.com/mitsuhiko/flask-sqlalchemy/pull/364
-.. _#373: https://github.com/mitsuhiko/flask-sqlalchemy/pull/373
-.. _#409: https://github.com/mitsuhiko/flask-sqlalchemy/pull/409
-.. _#443: https://github.com/mitsuhiko/flask-sqlalchemy/pull/443
-.. _#460: https://github.com/mitsuhiko/flask-sqlalchemy/pull/460
-.. _#461: https://github.com/mitsuhiko/flask-sqlalchemy/pull/461
-.. _#467: https://github.com/mitsuhiko/flask-sqlalchemy/pull/467
+In development, codename Dubnium
Version 2.1
-----------
diff -Nru flask-sqlalchemy-2.2/debian/changelog flask-sqlalchemy-2.1/debian/changelog
--- flask-sqlalchemy-2.2/debian/changelog 2017-06-27 15:19:53.000000000 +0000
+++ flask-sqlalchemy-2.1/debian/changelog 2017-06-27 15:57:20.000000000 +0000
@@ -1,11 +1,11 @@
-flask-sqlalchemy (2.2-1xenial1) xenial; urgency=medium
+flask-sqlalchemy (2.1-1xenial1) xenial; urgency=medium
* built for privacyidea
- -- Cornelius Kölbel Tue, 27 Jun 2017 17:19:53 +0200
+ -- Cornelius Kölbel Tue, 27 Jun 2017 17:57:20 +0200
-flask-sqlalchemy (2.2-1) unstable; urgency=low
+flask-sqlalchemy (2.1-1) unstable; urgency=low
* source package automatically created by stdeb 0.8.5
- -- Cornelius Kölbel Tue, 27 Jun 2017 17:19:52 +0200
+ -- Cornelius Kölbel Tue, 27 Jun 2017 17:57:18 +0200
diff -Nru flask-sqlalchemy-2.2/debian/compat flask-sqlalchemy-2.1/debian/compat
--- flask-sqlalchemy-2.2/debian/compat 2017-06-27 15:19:52.000000000 +0000
+++ flask-sqlalchemy-2.1/debian/compat 2017-06-27 15:57:18.000000000 +0000
@@ -1 +1 @@
-9
+7
diff -Nru flask-sqlalchemy-2.2/debian/control flask-sqlalchemy-2.1/debian/control
--- flask-sqlalchemy-2.2/debian/control 2017-06-27 15:19:52.000000000 +0000
+++ flask-sqlalchemy-2.1/debian/control 2017-06-27 15:57:18.000000000 +0000
@@ -2,9 +2,10 @@
Maintainer: Cornelius Kölbel
Section: python
Priority: optional
-Build-Depends: dh-python, python-setuptools (>= 0.6b3), python-all (>= 2.6.6-3), debhelper (>= 9)
-Standards-Version: 3.9.6
-Homepage: http://github.com/mitsuhiko/flask-sqlalchemy
+Build-Depends: python-setuptools (>= 0.6b3), python-all (>= 2.6.6-3), debhelper (>= 7)
+Standards-Version: 3.9.1
+
+
Package: python-flask-sqlalchemy
Architecture: all
@@ -25,3 +26,5 @@
.
.
+
+
diff -Nru flask-sqlalchemy-2.2/debian/rules flask-sqlalchemy-2.1/debian/rules
--- flask-sqlalchemy-2.2/debian/rules 2017-06-27 15:19:52.000000000 +0000
+++ flask-sqlalchemy-2.1/debian/rules 2017-06-27 15:57:18.000000000 +0000
@@ -1,8 +1,31 @@
#!/usr/bin/make -f
# This file was automatically generated by stdeb 0.8.5 at
-# Tue, 27 Jun 2017 17:19:52 +0200
-export PYBUILD_NAME=flask-sqlalchemy
+# Tue, 27 Jun 2017 17:57:18 +0200
+
%:
- dh $@ --with python2 --buildsystem=pybuild
+ dh $@ --with python2 --buildsystem=python_distutils
+
+
+override_dh_auto_clean:
+ python setup.py clean -a
+ find . -name \*.pyc -exec rm {} \;
+
+
+
+override_dh_auto_build:
+ python setup.py build --force
+
+
+
+override_dh_auto_install:
+ python setup.py install --force --root=debian/python-flask-sqlalchemy --no-compile -O0 --install-layout=deb --prefix=/usr
+
+
+
+override_dh_python2:
+ dh_python2 --no-guessing-versions
+
+
+
diff -Nru flask-sqlalchemy-2.2/debian/source/options flask-sqlalchemy-2.1/debian/source/options
--- flask-sqlalchemy-2.2/debian/source/options 1970-01-01 00:00:00.000000000 +0000
+++ flask-sqlalchemy-2.1/debian/source/options 2017-06-27 15:57:18.000000000 +0000
@@ -0,0 +1 @@
+extend-diff-ignore="\.egg-info$"
\ No newline at end of file
diff -Nru flask-sqlalchemy-2.2/debian/watch flask-sqlalchemy-2.1/debian/watch
--- flask-sqlalchemy-2.2/debian/watch 2017-06-27 15:19:52.000000000 +0000
+++ flask-sqlalchemy-2.1/debian/watch 1970-01-01 00:00:00.000000000 +0000
@@ -1,4 +0,0 @@
-# please also check http://pypi.debian.net/Flask-SQLAlchemy/watch
-version=3
-opts=uversionmangle=s/(rc|a|b|c)/~$1/ \
-http://pypi.debian.net/Flask-SQLAlchemy/Flask-SQLAlchemy-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz)))
\ No newline at end of file
diff -Nru flask-sqlalchemy-2.2/docs/api.rst flask-sqlalchemy-2.1/docs/api.rst
--- flask-sqlalchemy-2.2/docs/api.rst 2016-05-31 16:38:29.000000000 +0000
+++ flask-sqlalchemy-2.1/docs/api.rst 2015-07-28 19:15:32.000000000 +0000
@@ -1,7 +1,7 @@
API
---
-.. module:: flask_sqlalchemy
+.. module:: flask.ext.sqlalchemy
This part of the documentation documents all the public classes and
functions in Flask-SQLAlchemy.
@@ -12,6 +12,10 @@
.. autoclass:: SQLAlchemy
:members:
+ .. attribute:: Query
+
+ The :class:`BaseQuery` class.
+
Models
``````
@@ -31,7 +35,32 @@
explicitly, that will be used instead.
.. autoclass:: BaseQuery
- :members:
+ :members: get, get_or_404, paginate, first_or_404
+
+ .. method:: all()
+
+ Return the results represented by this query as a list. This
+ results in an execution of the underlying query.
+
+ .. method:: order_by(*criterion)
+
+ apply one or more ORDER BY criterion to the query and return the
+ newly resulting query.
+
+ .. method:: limit(limit)
+
+ Apply a LIMIT to the query and return the newly resulting query.
+
+ .. method:: offset(offset)
+
+ Apply an OFFSET to the query and return the newly resulting
+ query.
+
+ .. method:: first()
+
+ Return the first result of this query or `None` if the result
+ doesn’t contain any rows. This results in an execution of the
+ underlying query.
Sessions
````````
diff -Nru flask-sqlalchemy-2.2/docs/binds.rst flask-sqlalchemy-2.1/docs/binds.rst
--- flask-sqlalchemy-2.2/docs/binds.rst 2016-05-31 16:38:29.000000000 +0000
+++ flask-sqlalchemy-2.1/docs/binds.rst 2015-02-26 17:58:08.000000000 +0000
@@ -1,6 +1,6 @@
.. _binds:
-.. currentmodule:: flask_sqlalchemy
+.. currentmodule:: flask.ext.sqlalchemy
Multiple Databases with Binds
=============================
diff -Nru flask-sqlalchemy-2.2/docs/config.rst flask-sqlalchemy-2.1/docs/config.rst
--- flask-sqlalchemy-2.2/docs/config.rst 2016-10-28 14:21:05.000000000 +0000
+++ flask-sqlalchemy-2.1/docs/config.rst 2015-07-28 19:15:32.000000000 +0000
@@ -47,10 +47,7 @@
connections after 8 hours idle by
default. Note that Flask-SQLAlchemy
automatically sets this to 2 hours if
- MySQL is used. Some backends may use a
- different default timeout value. For more
- information about timeouts see
- :ref:`timeouts`.
+ MySQL is used.
``SQLALCHEMY_MAX_OVERFLOW`` Controls the number of connections that
can be created after the pool reached
its maximum size. When those additional
@@ -122,16 +119,17 @@
:class:`~sqlalchemy.schema.MetaData` object.
This allows you to, among other things,
specify a `custom constraint naming convention
-`_
-in conjunction with SQLAlchemy 0.9.2 or higher.
+`_.
Doing so is important for dealing with database migrations (for instance using
`alembic `_ as stated
-`here `_. Here's an
-example, as suggested by the SQLAlchemy docs::
+`here `_. Since SQL
+defines no standard naming conventions, there is no guaranteed nor effective
+compatibility by default among database implementations. You can define a
+custom naming convention like this as suggested by the SQLAlchemy docs::
from sqlalchemy import MetaData
from flask import Flask
- from flask_sqlalchemy import SQLAlchemy
+ from flask.ext.sqlalchemy import SQLAlchemy
convention = {
"ix": 'ix_%(column_0_label)s',
@@ -147,21 +145,3 @@
For more info about :class:`~sqlalchemy.schema.MetaData`,
`check out the official docs on it
`_.
-
-.. _timeouts:
-
-Timeouts
---------
-
-Certain database backends may impose different inactive connection timeouts,
-which interferes with Flask-SQLAlchemy's connection pooling.
-
-By default, MariaDB is configured to have a 600 second timeout. This often
-surfaces hard to debug, production environment only exceptions like ``2013: Lost connection to MySQL server during query``.
-
-If you are using a backend (or a pre-configured database-as-a-service) with a
-lower connection timeout, it is recommended that you set
-`SQLALCHEMY_POOL_RECYCLE` to a value less than your backend's timeout.
-
-
-
diff -Nru flask-sqlalchemy-2.2/docs/conf.py flask-sqlalchemy-2.1/docs/conf.py
--- flask-sqlalchemy-2.2/docs/conf.py 2016-06-14 14:39:26.000000000 +0000
+++ flask-sqlalchemy-2.1/docs/conf.py 2015-07-28 19:15:32.000000000 +0000
@@ -11,15 +11,12 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
-import os
-import sys
-from datetime import datetime
-import pkg_resources
+import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
-
+sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
sys.path.append(os.path.abspath('_themes'))
# -- General configuration -----------------------------------------------------
@@ -45,23 +42,24 @@
# General information about the project.
project = u'Flask-SQLAlchemy'
-copyright = u'2010 - {0}, Armin Ronacher'.format(datetime.utcnow().year)
+copyright = u'2010-2014, Armin Ronacher'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
+import pkg_resources
try:
release = pkg_resources.get_distribution('Flask-SQLAlchemy').version
except pkg_resources.DistributionNotFound:
- print('To build the documentation, the distribution information of')
+ print('To build the documentation, The distribution information of')
print('Flask-SQLAlchemy has to be available. Either install the package')
print('into your development environment or run "setup.py develop"')
print('to setup the metadata. A virtualenv is recommended!')
sys.exit(1)
+del pkg_resources
if 'dev' in release:
- release = ''.join(release.partition('dev')[:2])
-
+ release = release.split('dev')[0] + 'dev'
version = '.'.join(release.split('.')[:2])
# The language for content autogenerated by Sphinx. Refer to documentation
@@ -106,7 +104,7 @@
# further. For a list of options available for each theme, see the
# documentation.
html_theme_options = {
- 'index_logo': 'flask-sqlalchemy-title.png'
+ 'index_logo': 'flask-sqlalchemy.png'
}
# Add any paths that contain custom themes here, relative to this directory.
@@ -143,8 +141,9 @@
# Custom sidebar templates, maps document names to template names.
html_sidebars = {
- 'index': ['sidebarlogo.html', 'sidebarintro.html', 'sourcelink.html', 'searchbox.html'],
- '**': ['sidebarlogo.html', 'localtoc.html', 'relations.html', 'sourcelink.html', 'searchbox.html']
+ 'index': ['sidebarintro.html', 'sourcelink.html', 'searchbox.html'],
+ '**': ['sidebarlogo.html', 'localtoc.html', 'relations.html',
+ 'sourcelink.html', 'searchbox.html']
}
# Additional templates that should be rendered to pages, maps page names to
@@ -225,11 +224,9 @@
# Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {
- 'python': ('https://docs.python.org/3/', None),
- 'flask': ('http://flask.pocoo.org/docs/', None),
- 'sqlalchemy': ('http://docs.sqlalchemy.org/en/latest/', None)
-}
+intersphinx_mapping = {'http://docs.python.org/': None,
+ 'http://flask.pocoo.org/docs/': None,
+ 'http://www.sqlalchemy.org/docs/': None}
pygments_style = 'flask_theme_support.FlaskyStyle'
# fall back if theme is not there
diff -Nru flask-sqlalchemy-2.2/docs/contents.rst.inc flask-sqlalchemy-2.1/docs/contents.rst.inc
--- flask-sqlalchemy-2.2/docs/contents.rst.inc 2016-10-28 14:21:05.000000000 +0000
+++ flask-sqlalchemy-2.1/docs/contents.rst.inc 2015-02-26 17:58:08.000000000 +0000
@@ -14,7 +14,6 @@
queries
binds
signals
- customizing
API Reference
-------------
diff -Nru flask-sqlalchemy-2.2/docs/contexts.rst flask-sqlalchemy-2.1/docs/contexts.rst
--- flask-sqlalchemy-2.2/docs/contexts.rst 2016-05-31 16:38:29.000000000 +0000
+++ flask-sqlalchemy-2.1/docs/contexts.rst 2015-07-28 19:15:32.000000000 +0000
@@ -1,6 +1,6 @@
.. _contexts:
-.. currentmodule:: flask_sqlalchemy
+.. currentmodule:: flask.ext.sqlalchemy
Introduction into Contexts
==========================
@@ -31,7 +31,7 @@
:class:`SQLAlchemy` object to your application. Why doesn't it do that?
Because there might be more than one application created.
-So how does :class:`SQLAlchemy` come to know about your application?
+So how does :class:`SQLAlchemy` now really know about your application?
You will have to setup an application context. If you are working inside
a Flask view function, that automatically happens. However if you are
working inside the interactive shell, you will have to do that yourself
@@ -44,7 +44,7 @@
>>> app = create_app()
>>> app.app_context().push()
-Alternatively, use the with-statement to take care of setup and teardown::
+Inside scripts it makes also sense to use the with-statement::
def my_function():
with app.app_context():
diff -Nru flask-sqlalchemy-2.2/docs/customizing.rst flask-sqlalchemy-2.1/docs/customizing.rst
--- flask-sqlalchemy-2.2/docs/customizing.rst 2016-10-28 14:21:05.000000000 +0000
+++ flask-sqlalchemy-2.1/docs/customizing.rst 1970-01-01 00:00:00.000000000 +0000
@@ -1,123 +0,0 @@
-.. _customizing:
-
-.. currentmodule:: flask_sqlalchemy
-
-Customizing
-===========
-
-Flask-SQLAlchemy defines sensible defaults. However, sometimes customization is
-needed. Two major pieces to customize are the Model base class and the default
-Query class.
-
-Both of these customizations are applied at the creation of the :class:`SQLAlchemy`
-object and extend to all models derived from its ``Model`` class.
-
-Model Class
------------
-
-Flask-SQLAlchemy allows defining a custom declarative base, just like SQLAlchemy,
-that all model classes should extend from. For example, if all models should have
-a custom ``__repr__`` method::
-
- from flask_sqlalchemy import Model # this is the default declarative base
- from flask_sqlalchemy import SQLAlchemy
-
- class ReprBase(Model):
- def __repr__(self):
- return "<{0} id: {1}>".format(self.__class__.__name__, self.id)
-
- db = SQLAlchemy(model_class=ReprBase)
-
- class MyModel(db.Model):
- ...
-
-.. note::
-
- While not strictly necessary to inherit from :class:`flask_sqlalchemy.Model`
- it is encouraged as future changes may cause incompatibility.
-
-.. note::
-
- If behavior is needed in only some models, not all, a better strategy
- is to use a Mixin, as exampled below.
-
-While this particular example is more useful for debugging, it is possible to
-provide many augmentations to models that would otherwise be achieved with
-mixins instead. The above example is equivalent to the following::
-
- class ReprBase(object):
- def __repr__(self):
- return "<{0} id: {1}>".format(self.__class__.__name__, self.id)
-
- db = SQLAlchemy()
-
- class MyModel(db.Model, ReprBase):
- ...
-
-It also possible to provide default columns and properties to all models as well::
-
- from flask_sqlalchemy import Model, SQLAlchemy
- from sqlalchemy import Column, DateTime
- from datetime import datetime
-
- class TimestampedModel(Model):
- created_at = Column(DateTime, default=datetime.utcnow)
-
- db = SQLAlchemy(model_class=TimestampedModel)
-
- class MyModel(db.Model):
- ...
-
-All model classes extending from ``db.Model`` will now inherit a
-``created_at`` column.
-
-Query Class
------------
-
-It is also possible to customize what is availble for use on the
-special ``query`` property of models. For example, providing a
-``get_or`` method::
-
- from flask_sqlalchemy import BaseQuery, SQLAlchemy
-
- class GetOrQuery(BaseQuery):
- def get_or(self, ident, default=None):
- return self.get(ident) or default
-
- db = SQLAlchemy(query_class=GetOrQuery)
-
-And now all queries executed from the special ``query`` property
-on Flask-SQLAlchemy models can use the ``get_or`` method as part
-of their queries. All relationships defined with
-``db.relationship`` (but not :func:`sqlalchemy.relationship`)
-will also be provided with this functionality.
-
-.. warning::
-
- Unlike a custom ``Model`` base class, it is required
- to either inherit from either :class:`flask_sqlalchemy.BaseQuery`
- or :func:`sqlalchemy.orm.Query` in order to define a custom
- query class.
-
-It also possible to define a custom query class for individual
-relationships as well, by providing the ``query_class`` keyword
-in the definition. This works with both ``db.relationship``
-and ``sqlalchemy.relationship``::
-
- class MyModel(db.Model):
- cousin = db.relationship('OtherModel', query_class=GetOrQuery)
-
-.. note::
-
- If a query class is defined on a relationship, it will take
- precedence over the query class attached to its corresponding
- model.
-
-It is also possible to define a specific query class for individual models
-by overriding the ``query_class`` class attribute on the model::
-
- class MyModel(db.Model):
- query_class = GetOrQuery
-
-In this case, the ``get_or`` method will be only availble on queries
-orginating from ``MyModel.query``.
diff -Nru flask-sqlalchemy-2.2/docs/index.rst flask-sqlalchemy-2.1/docs/index.rst
--- flask-sqlalchemy-2.2/docs/index.rst 2016-05-31 16:38:29.000000000 +0000
+++ flask-sqlalchemy-2.1/docs/index.rst 2015-02-26 17:58:08.000000000 +0000
@@ -3,10 +3,10 @@
Flask-SQLAlchemy
================
-.. module:: flask_sqlalchemy
+.. module:: flask.ext.sqlalchemy
Flask-SQLAlchemy is an extension for `Flask`_ that adds support for
-`SQLAlchemy`_ to your application. It requires SQLAlchemy 0.8 or
+`SQLAlchemy`_ to your application. It requires SQLAlchemy 0.6 or
higher. It aims to simplify using SQLAlchemy with Flask by providing
useful defaults and extra helpers that make it easier to accomplish common
tasks.
@@ -16,8 +16,4 @@
.. _example sourcecode:
http://github.com/mitsuhiko/flask-sqlalchemy/tree/master/examples/
-See `the SQLAlchemy documentation`_ to learn how to work with the ORM in depth. The following documentation is a brief overview of the most common tasks, as well as the features specific to Flask-SQLAlchemy.
-
-.. _the SQLAlchemy documentation: http://docs.sqlalchemy.org/
-
.. include:: contents.rst.inc
diff -Nru flask-sqlalchemy-2.2/docs/models.rst flask-sqlalchemy-2.1/docs/models.rst
--- flask-sqlalchemy-2.2/docs/models.rst 2017-01-14 19:57:27.000000000 +0000
+++ flask-sqlalchemy-2.1/docs/models.rst 2015-02-26 17:58:08.000000000 +0000
@@ -1,6 +1,6 @@
.. _models:
-.. currentmodule:: flask_sqlalchemy
+.. currentmodule:: flask.ext.sqlalchemy
Declaring Models
================
@@ -12,14 +12,13 @@
Things to keep in mind:
-- The baseclass for all your models is called ``db.Model``. It's stored
+- The baseclass for all your models is called `db.Model`. It's stored
on the SQLAlchemy instance you have to create. See :ref:`quickstart`
for more details.
- 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.
+ to lowercase and with “CamelCase” converted to “camel_case”.
Simple Example
--------------
@@ -28,13 +27,17 @@
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)
+ 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
def __repr__(self):
return '' % self.username
-Use :class:`~sqlalchemy.schema.Column` to define a column. The name of the
+Use :class:`~sqlalchemy.Column` to define a column. The name of the
column is the name you assign it to. If you want to use a different name
in the table you can provide an optional first argument which is a string
with the desired column name. Primary keys are marked with
@@ -42,94 +45,78 @@
which case they become a compound primary key.
The types of the column are the first argument to
-:class:`~sqlalchemy.schema.Column`. You can either provide them directly
-or call them to further specify them (like providing a length). The
-following types are the most common:
-
-================================================ =====================================
-:class:`~sqlalchemy.types.Integer` an integer
-:class:`String(size) ` a string with a maximum length
- (optional in some databases, e.g.
- PostgreSQL)
-:class:`~sqlalchemy.types.Text` some longer unicode text
-:class:`~sqlalchemy.types.DateTime` date and time expressed as Python
- :class:`~datetime.datetime` object.
-:class:`~sqlalchemy.types.Float` stores floating point values
-:class:`~sqlalchemy.types.Boolean` stores a boolean value
-:class:`~sqlalchemy.types.PickleType` stores a pickled Python object
-:class:`~sqlalchemy.types.LargeBinary` stores large arbitrary binary data
-================================================ =====================================
+:class:`~sqlalchemy.Column`. You can either provide them directly or call
+them to further specify them (like providing a length). The following
+types are the most common:
+
+=================== =====================================
+`Integer` an integer
+`String` (size) a string with a maximum length
+`Text` some longer unicode text
+`DateTime` date and time expressed as Python
+ :mod:`~datetime.datetime` object.
+`Float` stores floating point values
+`Boolean` stores a boolean value
+`PickleType` stores a pickled Python object
+`LargeBinary` stores large arbitrary binary data
+=================== =====================================
One-to-Many Relationships
-------------------------
The most common relationships are one-to-many relationships. Because
relationships are declared before they are established you can use strings
-to refer to classes that are not created yet (for instance if ``Person``
-defines a relationship to ``Address`` which is declared later in the file).
+to refer to classes that are not created yet (for instance if `Person`
+defines a relationship to `Article` which is declared later in the file).
Relationships are expressed with the :func:`~sqlalchemy.orm.relationship`
function. However the foreign key has to be separately declared with the
-:class:`~sqlalchemy.schema.ForeignKey` class::
+:class:`sqlalchemy.schema.ForeignKey` class::
class Person(db.Model):
id = db.Column(db.Integer, primary_key=True)
- name = db.Column(db.String(50), nullable=False)
- addresses = db.relationship('Address', backref='person', lazy=True)
+ name = db.Column(db.String(50))
+ addresses = db.relationship('Address', backref='person',
+ lazy='dynamic')
class Address(db.Model):
id = db.Column(db.Integer, primary_key=True)
- email = db.Column(db.String(120), nullable=False)
- person_id = db.Column(db.Integer, db.ForeignKey('person.id'),
- nullable=False)
-
-What does :func:`db.relationship() ` do?
-That function returns a new property that can do multiple things.
-In this case we told it to point to the ``Address`` class and load
-multiple of those. How does it know that this will return more than
-one address? Because SQLAlchemy guesses a useful default from your
-declaration. If you would want to have a one-to-one relationship you
-can pass ``uselist=False`` to :func:`~sqlalchemy.orm.relationship`.
-
-Since a person with no name or an email address with no address associated
-makes no sense, ``nullable=False`` tells SQLAlchemy to create the column
-as ``NOT NULL``. This is implied for primary key columns, but it's a good
-idea to specify it for all other columns to make it clear to other people
-working on your code that you did actually want a nullable column and did
-not just forget to add it.
-
-So what do ``backref`` and ``lazy`` mean? ``backref`` is a simple way to also
-declare a new property on the ``Address`` class. You can then also use
-``my_address.person`` to get to the person at that address. ``lazy`` defines
+ email = db.Column(db.String(50))
+ person_id = db.Column(db.Integer, db.ForeignKey('person.id'))
+
+What does ``db.relationship()`` do? That function returns a new property
+that can do multiple things. In this case we told it to point to the
+`Address` class and load multiple of those. How does it know that this
+will return more than one address? Because SQLAlchemy guesses a useful
+default from your declaration. If you would want to have a one-to-one
+relationship you can pass ``uselist=False`` to
+:func:`~sqlalchemy.orm.relationship`.
+
+So what do `backref` and `lazy` mean? `backref` is a simple way to also
+declare a new property on the `Address` class. You can then also use
+``my_address.person`` to get to the person at that address. `lazy` defines
when SQLAlchemy will load the data from the database:
-- ``'select'`` / ``True`` (which is the default, but explicit is better
- than implicit) means that SQLAlchemy will load the data as necessary
- in one go using a standard select statement.
-- ``'joined'`` / ``False`` tells SQLAlchemy to load the relationship in
- the same query as the parent using a ``JOIN`` statement.
+- ``'select'`` (which is the default) means that SQLAlchemy will load
+ the data as necessary in one go using a standard select statement.
+- ``'joined'`` tells SQLAlchemy to load the relationship in the same
+ query as the parent using a `JOIN` statement.
- ``'subquery'`` works like ``'joined'`` but instead SQLAlchemy will
use a subquery.
-- ``'dynamic'`` is special and can be useful if you have many items
- and always want to apply additional SQL filters to them.
- Instead of loading the items SQLAlchemy will return another query
- object which you can further refine before loading the items.
- Note that this cannot be turned into a different loading strategy
- when querying so it's often a good idea to avoid using this in
- favor of ``lazy=True``. A query object equivalent to a dynamic
- ``user.addresses`` relationship can be created using
- :meth:`Address.query.with_parent(user) `
- while still being able to use
- lazy or eager loading on the relationship itself as necessary.
+- ``'dynamic'`` is special and useful if you have many items. Instead of
+ loading the items SQLAlchemy will return another query object which
+ you can further refine before loading the items. This is usually
+ what you want if you expect more than a handful of items for this
+ relationship.
How do you define the lazy status for backrefs? By using the
:func:`~sqlalchemy.orm.backref` function::
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
- name = db.Column(db.String(50), nullable=False)
- addresses = db.relationship('Address', lazy='select',
- backref=db.backref('person', lazy='joined'))
+ name = db.Column(db.String(50))
+ addresses = db.relationship('Address',
+ backref=db.backref('person', lazy='joined'), lazy='dynamic')
Many-to-Many Relationships
--------------------------
@@ -139,31 +126,19 @@
is strongly recommended to *not* use a model but an actual table::
tags = db.Table('tags',
- db.Column('tag_id', db.Integer, db.ForeignKey('tag.id'), primary_key=True),
- db.Column('page_id', db.Integer, db.ForeignKey('page.id'), primary_key=True)
+ db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')),
+ db.Column('page_id', db.Integer, db.ForeignKey('page.id'))
)
class Page(db.Model):
id = db.Column(db.Integer, primary_key=True)
- tags = db.relationship('Tag', secondary=tags, lazy='subquery',
- backref=db.backref('pages', lazy=True))
+ tags = db.relationship('Tag', secondary=tags,
+ backref=db.backref('pages', lazy='dynamic'))
class Tag(db.Model):
id = db.Column(db.Integer, primary_key=True)
-Here we configured ``Page.tags`` to be loaded immediately after loading
-a Page, but using a separate query. This always results in two
-queries when retrieving a Page, but when querying for multiple pages
-you will not get additional queries.
-
-The list of pages for a tag on the other hand is something that's
-rarely needed. For example, you won't need that list when retrieving
-the tags for a specific page. Therefore, the backref is set to be
-lazy-loaded so that accessing it for the first time will trigger a
-query to get the list of pages for that tag. If you need to apply
-further query options on that list, you could either switch to the
-``'dynamic'`` strategy - with the drawbacks mentioned above - or get
-a query object using
-:meth:`Page.query.with_parent(some_tag) `
-and then use it exactly as you would with the query object from a dynamic
-relationship.
+Here we configured `Page.tags` to be a list of tags once loaded because we
+don't expect too many tags per page. The list of pages per tag
+(`Tag.pages`) however is a dynamic backref. As mentioned above this means
+that you will get a query object back you can use to fire a select yourself.
diff -Nru flask-sqlalchemy-2.2/docs/queries.rst flask-sqlalchemy-2.1/docs/queries.rst
--- flask-sqlalchemy-2.2/docs/queries.rst 2016-05-31 16:38:29.000000000 +0000
+++ flask-sqlalchemy-2.1/docs/queries.rst 2015-02-26 17:58:08.000000000 +0000
@@ -1,4 +1,4 @@
-.. currentmodule:: flask_sqlalchemy
+.. currentmodule:: flask.ext.sqlalchemy
Select, Insert, Delete
======================
@@ -80,7 +80,7 @@
>>> peter = User.query.filter_by(username='peter').first()
>>> peter.id
-2
+1
>>> peter.email
u'peter@example.org'
@@ -97,7 +97,7 @@
Ordering users by something:
->>> User.query.order_by(User.username).all()
+>>> User.query.order_by(User.username)
[, , ]
Limiting users:
diff -Nru flask-sqlalchemy-2.2/docs/quickstart.rst flask-sqlalchemy-2.1/docs/quickstart.rst
--- flask-sqlalchemy-2.2/docs/quickstart.rst 2017-01-14 19:57:27.000000000 +0000
+++ flask-sqlalchemy-2.1/docs/quickstart.rst 2015-07-28 19:15:32.000000000 +0000
@@ -3,7 +3,7 @@
Quickstart
==========
-.. currentmodule:: flask_sqlalchemy
+.. currentmodule:: flask.ext.sqlalchemy
Flask-SQLAlchemy is fun to use, incredibly easy for basic applications, and
readily extends for larger applications. For the complete guide, checkout
@@ -18,7 +18,7 @@
Once created, that object then contains all the functions and helpers
from both :mod:`sqlalchemy` and :mod:`sqlalchemy.orm`. Furthermore it
-provides a class called ``Model`` that is a declarative base which can be
+provides a class called `Model` that is a declarative base which can be
used to declare models::
from flask import Flask
@@ -31,51 +31,42 @@
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)
+ 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
def __repr__(self):
return '' % self.username
-To create the initial database, just import the ``db`` object from an
+To create the initial database, just import the `db` object from an
interactive Python shell and run the
:meth:`SQLAlchemy.create_all` method to create the
-tables and database::
+tables and database:
+
+>>> from yourapplication import db
+>>> db.create_all()
+
+Boom, and there is your database. Now to create some users:
- >>> from yourapplication import db
- >>> db.create_all()
+>>> from yourapplication import User
+>>> admin = User('admin', 'admin@example.com')
+>>> guest = User('guest', 'guest@example.com')
-Boom, and there is your database. Now to create some users::
+But they are not yet in the database, so let's make sure they are:
- >>> from yourapplication import User
- >>> admin = User(username='admin', email='admin@example.com')
- >>> guest = User(username='guest', email='guest@example.com')
-
-But they are not yet in the database, so let's make sure they are::
-
- >>> db.session.add(admin)
- >>> db.session.add(guest)
- >>> db.session.commit()
-
-Accessing the data in database is easy as a pie::
-
- >>> User.query.all()
- [, ]
- >>> User.query.filter_by(username='admin').first()
-
-
-Note how we never defined a ``__init__`` method on the ``User`` class?
-That's because SQLAlchemy adds an implicit constructor to all model
-classes which accepts keyword arguments for all its columns and
-relationships. If you decide to override the constructor for any
-reason, make sure to keep accepting ``**kwargs`` and call the super
-constructor with those ``**kwargs`` to preserve this behavior::
-
- class Foo(db.Model):
- # ...
- def __init__(**kwargs):
- super(Foo, self).__init__(**kwargs)
- # do custom stuff
+>>> db.session.add(admin)
+>>> db.session.add(guest)
+>>> db.session.commit()
+
+Accessing the data in database is easy as a pie:
+
+>>> users = User.query.all()
+[, ]
+>>> admin = User.query.filter_by(username='admin').first()
+
Simple Relationships
--------------------
@@ -84,20 +75,27 @@
are really good at are relations. As such, we shall have an example of an
application that uses two tables that have a relationship to each other::
+
from datetime import datetime
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
- title = db.Column(db.String(80), nullable=False)
- body = db.Column(db.Text, nullable=False)
- pub_date = db.Column(db.DateTime, nullable=False,
- default=datetime.utcnow)
+ title = db.Column(db.String(80))
+ body = db.Column(db.Text)
+ pub_date = db.Column(db.DateTime)
- category_id = db.Column(db.Integer, db.ForeignKey('category.id'),
- nullable=False)
+ category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
category = db.relationship('Category',
- backref=db.backref('posts', lazy=True))
+ backref=db.backref('posts', lazy='dynamic'))
+
+ def __init__(self, title, body, category, pub_date=None):
+ self.title = title
+ self.body = body
+ if pub_date is None:
+ pub_date = datetime.utcnow()
+ self.pub_date = pub_date
+ self.category = category
def __repr__(self):
return '' % self.title
@@ -105,54 +103,32 @@
class Category(db.Model):
id = db.Column(db.Integer, primary_key=True)
- name = db.Column(db.String(50), nullable=False)
+ name = db.Column(db.String(50))
+
+ def __init__(self, name):
+ self.name = name
def __repr__(self):
return '' % self.name
-First let's create some objects::
+First let's create some objects:
+
+>>> py = Category('Python')
+>>> p = Post('Hello Python!', 'Python is pretty cool', py)
+>>> db.session.add(py)
+>>> db.session.add(p)
+
+Now because we declared `posts` as dynamic relationship in the backref
+it shows up as query:
+
+>>> py.posts
+
- >>> py = Category(name='Python')
- >>> Post(title='Hello Python!', body='Python is pretty cool', category=py)
- >>> p = Post(title='Snakes', body='Ssssssss')
- >>> py.posts.append(p)
- >>> db.session.add(py)
-
-As you can see, there is no need to add the ``Post`` objects to the
-session. Since the ``Category`` is part of the session all objects
-associated with it through relationships will be added too. It does
-not matter whether :meth:`db.session.add() `
-is called before or after creating these objects. The association can
-also be done on either side of the relationship - so a post can be
-created with a category or it can be added to the list of posts of
-the category.
-
-Let's look at the posts. Accessing them will load them from the database
-since the relationship is lazy-loaded, but you will probably not notice
-the difference - loading a list is quite fast::
-
- >>> py.posts
- [, ]
-
-While lazy-loading a relationship is fast, it can easily become a major
-bottleneck when you end up triggering extra queries in a loop for more
-than a few objects. For this case, SQLAlchemy lets you override the
-loading strategy on the query level. If you wanted a single query to
-load all categories and their posts, you could do it like this::
-
- >>> from sqlalchemy.orm import joinedload
- >>> query = Category.query.options(joinedload('posts'))
- >>> for category in query:
- ... print category, category.posts
- [, ]
-
-
-If you want to get a query object for that relationship, you can do so
-using :meth:`~sqlalchemy.orm.query.Query.with_parent`. Let's exclude
-that post about Snakes for example::
+It behaves like a regular query object so we can ask it for all posts that
+are associated with our test “Python” category:
- >>> Post.query.with_parent(py).filter(Post.title != 'Snakes').all()
- []
+>>> py.posts.all()
+[]
Road to Enlightenment
@@ -164,7 +140,7 @@
- all the functions and classes from :mod:`sqlalchemy` and
:mod:`sqlalchemy.orm`
- - a preconfigured scoped session called ``session``
+ - a preconfigured scoped session called `session`
- the :attr:`~SQLAlchemy.metadata`
- the :attr:`~SQLAlchemy.engine`
- a :meth:`SQLAlchemy.create_all` and :meth:`SQLAlchemy.drop_all`
@@ -172,7 +148,7 @@
- a :class:`Model` baseclass that is a configured declarative base.
2. The :class:`Model` declarative base class behaves like a regular
- Python class but has a ``query`` attribute attached that can be used to
+ Python class but has a `query` attribute attached that can be used to
query the model. (:class:`Model` and :class:`BaseQuery`)
3. You have to commit the session, but you don't have to remove it at
Binary files /tmp/tmpAAF4Ri/KAnyR0sCfq/flask-sqlalchemy-2.2/docs/_static/flask-sqlalchemy-logo.png and /tmp/tmpAAF4Ri/VZbze0IV0W/flask-sqlalchemy-2.1/docs/_static/flask-sqlalchemy-logo.png differ
Binary files /tmp/tmpAAF4Ri/KAnyR0sCfq/flask-sqlalchemy-2.2/docs/_static/flask-sqlalchemy.png and /tmp/tmpAAF4Ri/VZbze0IV0W/flask-sqlalchemy-2.1/docs/_static/flask-sqlalchemy.png differ
Binary files /tmp/tmpAAF4Ri/KAnyR0sCfq/flask-sqlalchemy-2.2/docs/_static/flask-sqlalchemy-small.png and /tmp/tmpAAF4Ri/VZbze0IV0W/flask-sqlalchemy-2.1/docs/_static/flask-sqlalchemy-small.png differ
Binary files /tmp/tmpAAF4Ri/KAnyR0sCfq/flask-sqlalchemy-2.2/docs/_static/flask-sqlalchemy-title.png and /tmp/tmpAAF4Ri/VZbze0IV0W/flask-sqlalchemy-2.1/docs/_static/flask-sqlalchemy-title.png differ
diff -Nru flask-sqlalchemy-2.2/docs/_templates/sidebarintro.html flask-sqlalchemy-2.1/docs/_templates/sidebarintro.html
--- flask-sqlalchemy-2.2/docs/_templates/sidebarintro.html 2016-06-14 14:30:02.000000000 +0000
+++ flask-sqlalchemy-2.1/docs/_templates/sidebarintro.html 2015-02-26 17:58:08.000000000 +0000
@@ -1,16 +1,27 @@
+
About
+
+ Flask-SQLAlchemy provides a SQLAlchemy extension to Flask.
+ Flask is a micro webdevelopment framework for Python. You are currently
+ looking at the documentation of the development version. Things are
+ not stable yet, but if you have some feedback,
+ let me know.
+