Changes
*******


Version 3.1.1
=============

Released 2023-09-11

* Deprecate the "__version__" attribute. Use feature detection, or
  "importlib.metadata.version("flask-sqlalchemy")", instead. #5230


Version 3.1.0
=============

Released 2023-09-11

* Drop support for Python 3.7.  #1251

* Add support for the SQLAlchemy 2.x API via "model_class" parameter.
  #1140

* Bump minimum version of SQLAlchemy to 2.0.16.

* Remove previously deprecated code.

* Pass extra keyword arguments from "get_or_404" to "session.get".
  #1149

* Fix bug with finding right bind key for clause statements. #1211


Version 3.0.5
=============

Released 2023-06-21

* "Pagination.next()" enforces "max_per_page". #1201

* Improve type hint for "get_or_404" return value to be non-optional.
  #1226


Version 3.0.4
=============

Released 2023-06-19

* Fix type hint for "get_or_404" return value. #1208

* Fix type hints for pyright (used by VS Code Pylance extension).
  #1205


Version 3.0.3
=============

Released 2023-01-31

* Show helpful errors when mistakenly using multiple "SQLAlchemy"
  instances for the same app, or without calling "init_app". #1151

* Fix issue with getting the engine associated with a model that uses
  polymorphic table inheritance. #1155


Version 3.0.2
=============

Released 2022-10-14

* Update compatibility with SQLAlchemy 2. #1122


Version 3.0.1
=============

Released 2022-10-11

* Export typing information instead of using external typeshed
  definitions. #1112

* If default engine options are set, but "SQLALCHEMY_DATABASE_URI" is
  not set, an invalid default bind will not be configured. #1117


Version 3.0.0
=============

Released 2022-10-04

* Drop support for Python 2, 3.4, 3.5, and 3.6.

* Bump minimum version of Flask to 2.2.

* Bump minimum version of SQLAlchemy to 1.4.18.

* Remove previously deprecated code.

* The session is scoped to the current app context instead of the
  thread. This requires that an app context is active. This ensures
  that the session is cleaned up after every request.

* An active Flask application context is always required to access
  "session" and "engine", regardless of if an application was passed
  to the constructor. #508#944

* Different bind keys use different SQLAlchemy "MetaData" registries,
  allowing tables in different databases to have the same name. Bind
  keys are stored and looked up on the resulting metadata rather than
  the model or table.

* "SQLALCHEMY_DATABASE_URI" does not default to "sqlite:///:memory:".
  An error is raised if neither it nor "SQLALCHEMY_BINDS" define any
  engines. #731

* Configuring SQLite with a relative path is relative to
  "app.instance_path" instead of "app.root_path". The instance folder
  is created if necessary. #462

* Added "get_or_404", "first_or_404", "one_or_404", and "paginate"
  methods to the extension object. These use SQLAlchemy's preferred
  "session.execute(select())" pattern instead of the legacy query
  interface. #1088

* Setup methods that create the engines and session are renamed with a
  leading underscore. They are considered internal interfaces which
  may change at any time.

* All parameters to "SQLAlchemy" except "app" are keyword-only.

* Renamed the "bind" parameter to "bind_key" and removed the "app"
  parameter from various "SQLAlchemy" methods.

* The extension object uses "__getattr__" to alias names from the
  SQLAlchemy package, rather than copying them as attributes.

* The extension object is stored directly as
  "app.extensions["sqlalchemy"]". #698

* The session class can be customized by passing the "class_" key in
  the "session_options" parameter. #327

* "SignallingSession" is renamed to "Session".

* "Session.get_bind" more closely matches the base implementation.

* Model classes and the "db" instance are available without imports in
  "flask shell". #1089

* The "CamelCase" to "snake_case" table name converter handles more
  patterns correctly. If model that was already created in the
  database changed, either use Alembic to rename the table, or set
  "__tablename__" to keep the old name. #406

* "Model" "repr" distinguishes between transient and pending
  instances. #967

* A custom model class can implement "__init_subclass__" with class
  parameters. #1002

* "db.Table" is a subclass instead of a function.

* The "engine_options" parameter is applied as defaults before per-
  engine configuration.

* "SQLALCHEMY_BINDS" values can either be an engine URL, or a dict of
  engine options including URL, for each bind.
  "SQLALCHEMY_DATABASE_URI" and "SQLALCHEMY_ENGINE_OPTIONS" correspond
  to the "None" key and take precedence. #783

* Engines are created when calling "init_app" rather than the first
  time they are accessed. #698

* "db.engines" exposes the map of bind keys to engines for the current
  app.

* "get_engine", "get_tables_for_bind", and "get_binds" are deprecated.

* SQLite driver-level URIs that look like
  "sqlite:///file:name.db?uri=true" are supported. #998#1045

* SQLite engines do not use "NullPool" if "pool_size" is 0.

* MySQL engines use the "utf8mb4" charset by default. #875

* MySQL engines do not set "pool_size" to 10.

* MySQL engines don't set a default for "pool_recycle" if not using a
  queue pool. #803

* "Query" is renamed from "BaseQuery".

* Added "Query.one_or_404".

* The query class is applied to "backref" in "relationship". #417

* Creating "Pagination" objects manually is no longer a public API.
  They should be created with "db.paginate" or "query.paginate". #1088

* "Pagination.iter_pages" and "Query.paginate" parameters are keyword-
  only.

* "Pagination" is iterable, iterating over its items. #70

* Pagination count query is more efficient.

* "Pagination.iter_pages" is more efficient. #622

* "Pagination.iter_pages" "right_current" parameter is inclusive.

* Pagination "per_page" cannot be 0. #1091

* Pagination "max_per_page" defaults to 100. #1091

* Added "Pagination.first" and "last" properties, which give the
  number of the first and last item on the page. #567

* "SQLALCHEMY_RECORD_QUERIES" is disabled by default, and is not
  enabled automatically with "app.debug" or "app.testing". #1092

* "get_debug_queries" is renamed to "get_recorded_queries" to better
  match the config and functionality.

* Recorded query info is a dataclass instead of a tuple. The "context"
  attribute is renamed to "location". Finding the location uses a more
  inclusive check.

* "SQLALCHEMY_TRACK_MODIFICATIONS" is disabled by default. #727

* "SQLALCHEMY_COMMIT_ON_TEARDOWN" is deprecated. It can cause various
  design issues that are difficult to debug. Call
  "db.session.commit()" directly instead. #216


Version 2.5.1
=============

Released 2021-03-18

* Fix compatibility with Python 2.7.


Version 2.5.0
=============

Released 2021-03-18

* Update to support SQLAlchemy 1.4.

* SQLAlchemy "URL" objects are immutable. Some internal methods have
  changed to return a new URL instead of "None". #885


Version 2.4.4
=============

Released 2020-07-14

* Change base class of meta mixins to "type". This fixes an issue
  caused by a regression in CPython 3.8.4. #852


Version 2.4.3
=============

Released 2020-05-26

* Deprecate "SQLALCHEMY_COMMIT_ON_TEARDOWN" as it can cause various
  design issues that are difficult to debug. Call
  "db.session.commit()" directly instead. #216


Version 2.4.2
=============

Released 2020-05-25

* Fix bad pagination when records are de-duped. #812


Version 2.4.1
=============

Released 2019-09-24

* Fix "AttributeError" when using multiple binds with polymorphic
  models. #651


Version 2.4.0
=============

Released 2019-04-24

* Drop support for Python 2.6 and 3.3. #687

* Address SQLAlchemy 1.3 deprecations. #684

* Make engine configuration more flexible. Added the "engine_options"
  parameter and "SQLALCHEMY_ENGINE_OPTIONS" config. Deprecated the
  individual engine option config keys "SQLALCHEMY_NATIVE_UNICODE",
  "SQLALCHEMY_POOL_SIZE", "SQLALCHEMY_POOL_TIMEOUT",
  "SQLALCHEMY_POOL_RECYCLE", and "SQLALCHEMY_MAX_OVERFLOW". #684

* "get_or_404()" and "first_or_404()" now accept a "description"
  parameter to control the 404 message. #636

* Use "time.perf_counter" for Python 3 on Windows. #638

* Add an example of Flask's tutorial project, Flaskr, adapted for
  Flask-SQLAlchemy. #720


Version 2.3.2
=============

Released 2017-10-11

* Don't mask the parent table for single-table inheritance models.
  #561


Version 2.3.1
=============

Released 2017-10-05

* If a model has a table name that matches an existing table in the
  metadata, use that table. Fixes a regression where reflected tables
  were not picked up by models. #551

* Raise the correct error when a model has a table name but no primary
  key. #556

* Fix "repr" on models that don't have an identity because they have
  not been flushed yet. #555

* Allow specifying a "max_per_page" limit for pagination, to avoid
  users specifying high values in the request args. #542

* For "paginate" with "error_out=False", the minimum value for "page"
  is 1 and "per_page" is 0. #558


Version 2.3.0
=============

Released 2017-09-28

* Multiple bugs with "__tablename__" generation are fixed. Names will
  be generated for models that define a primary key, but not for
  single-table inheritance subclasses. Names will not override a
  "declared_attr". "PrimaryKeyConstraint" is detected. #541

* Passing an existing "declarative_base()" as "model_class" to
  "SQLAlchemy.__init__" will use this as the base class instead of
  creating one. This allows customizing the metaclass used to
  construct the base. #546

* The undocumented "DeclarativeMeta" internals that the extension uses
  for binds and table name generation have been refactored to work as
  mixins. Documentation is added about how to create a custom
  metaclass that does not do table name generation. #546

* Model and metaclass code has been moved to a new "models" module.
  "_BoundDeclarativeMeta" is renamed to "DefaultMeta"; the old name
  will be removed in 3.0. #546

* Models have a default "repr" that shows the model name and primary
  key. #530

* Fixed a bug where using "init_app" would cause connectors to always
  use the "current_app" rather than the app they were created for.
  This caused issues when multiple apps were registered with the
  extension. #547


Version 2.2
===========

Released 2017-02-27, codename Dubnium

* 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 2.1
===========

Released 2015-10-23, codename Caesium

* Table names are automatically generated in more cases, including
  subclassing mixins and abstract models.

* Allow using a custom MetaData object.

* Add support for binds parameter to session.


Version 2.0
===========

Released 2014-08-29, codename Bohrium

* Changed how the builtin signals are subscribed to skip non-Flask-
  SQLAlchemy sessions. This will also fix the attribute error about
  model changes not existing.

* Added a way to control how signals for model modifications are
  tracked.

* Made the "SignallingSession" a public interface and added a hook for
  customizing session creation.

* If the "bind" parameter is given to the signalling session it will
  no longer cause an error that a parameter is given twice.

* Added working table reflection support.

* Enabled autoflush by default.

* Consider "SQLALCHEMY_COMMIT_ON_TEARDOWN" harmful and remove from
  docs.


Version 1.0
===========

Released 2013-07-20, codename Aurum

* Added Python 3.3 support.

* Dropped Python 2.5 compatibility.

* Various bugfixes.

* Changed versioning format to do major releases for each update now.


Version 0.16
============

* New distribution format (flask_sqlalchemy).

* Added support for Flask 0.9 specifics.


Version 0.15
============

* Added session support for multiple databases.


Version 0.14
============

* Make relative sqlite paths relative to the application root.


Version 0.13
============

* Fixed an issue with Flask-SQLAlchemy not selecting the correct
  binds.


Version 0.12
============

* Added support for multiple databases.

* Expose "BaseQuery" as "db.Query".

* Set default "query_class" for "db.relation", "db.relationship", and
  "db.dynamic_loader" to "BaseQuery".

* Improved compatibility with Flask 0.7.


Version 0.11
============

* Fixed a bug introduced in 0.10 with alternative table constructors.


Version 0.10
============

* Added support for signals.

* Table names are now automatically set from the class name unless
  overridden.

* "Model.query" now always works for applications directly passed to
  the "SQLAlchemy" constructor. Furthermore the property now raises a
  "RuntimeError" instead of being "None".

* Added session options to constructor.

* Fixed a broken "__repr__".

* "db.Table" is now a factory function that creates table objects.
  This makes it possible to omit the metadata.


Version 0.9
===========

* Applied changes to pass the Flask extension approval process.


Version 0.8
===========

* Added a few configuration keys for creating connections.

* Automatically activate connection recycling for MySQL connections.

* Added support for the Flask testing mode.


Version 0.7
===========

* Initial public release
