- Add django-style filter lookups:
contains,startswith,endswith,between,is_null,not_inandiregexp. - Fix SQLite index value inlining to apply properly.
- Fix
PostgresqlDatabase(isolation_level=...)having no effect on transactions. Previously onlyatomic(isolation_level=...)worked. - Fix
Ordering.collate()dropping thenulls=ordering. - Fix double-escaping of backticks in MySQL
get_indexes(). - Honor the
windows=parameter of theSelectconstructor. - Remove vestigial Python 2 compat (
reraise(),__div__,__nonzero__) and assorted dead internal code. - Remove
TimestampField.local_to_utc()andTimestampField.utc_to_local(). Select.columns()no longer accepts and ignores keyword arguments.- Remove unused
Metadata.get_rel_for_model(). - Fix
SelectBase.exists()ignoring itsdatabaseargument. - Fix
CursorWrapperindexing:cursor[n]raised IndexError for uncached rows andcursor[0]fetched the entire result set. - Fix
.namedtuples()crashing on selected columns that are not valid Python identifiers. - Preserve
materialized=when compounding CTEs viaunion()/union_all(). - Fix
ManyToManyFieldreads when the through-model foreign keys use the'!'backref sentinel. - Fix connection pooling with the
mariadbconnector - pooled connections were discarded on every checkout. - Fix
sqliteqstop()to drain the write queue and return True. - Fix apsw aggregate registration binding every name to the last-registered aggregate class.
- Fix two
NameErrors incysqlite_ext:blob_open()andprogress(). - Fix pwiz emitting an invalid
attr=keyword instead ofon_delete/on_updatefor reflected foreign keys. - Fix
datasetinfinite loop on self-referential foreign keys, crash on headerless CSV import,thaw()validating against export rather than import formats, and the importer mutating live model metadata. - Fix
model_to_dictto honoronly=/exclude=for many-to-many fields, fixresolve_multimodel_queryon queries with narrowed selections. - Fix
signals.Model.save(True)reportingcreated=Falsewhenforce_insertis passed positionally. - Fix
CompressedFieldcrashing onstrvalues. - Fix psycopg3 server-side cursors (missing
withhold) and CockroachDBrun_transactionretry detection under psycopg3. - Async queries are now logged to the
peeweelogger. - Remove dead code and unused imports throughout
playhouse; remove the broken, unusedget_current_url/get_next_urlhelpers fromflask_utils. - Fix
delete_instance(recursive=True)failing to cascade to the children of a model reachable through both nullable and non-nullable foreign-keys. - Fix subqueries losing their parentheses when used as a CASE value inside a single-argument function call, e.g.
fn.SUM(Case(...)). - Fix plain-
Tableinserts on returning-clause databases binding the primary-key name as a parameter and returning None instead of the new id. CompositeKeycomparisons raiseValueErrorwhen the value's length does not match the key, rather than silently matching on a prefix.- Async: connection-acquisition errors are translated to peewee exception types, matching query execution.
- Fix
FieldAlias.modelto reference the model alias rather than the aliased model; alias-rooted join queries no longer construct and discard a spurious instance of the aliased model for every result row. - Fix
playhouse.postgres_ext.JSONFieldcreatingjsonbcolumns after the core postgres backend began mapping the JSON field-type to JSONB; its DDL isjsonagain, and json-vs-jsonb function selection for chained lookups now follows the field's declared datatype. - Unaliased expressions in join queries now hydrate using the same cleaned attribute name as flat queries (e.g.
COUNTrather thanCOUNT(1). Field.__hash__is keyed on the model's schema and table-name rather than its class name, so same-named model classes (factories, separate modules, schema-per-tenant layouts) no longer collide in field-keyed registries such as backrefs; redefining or re-importing a model in place still replaces its entries.- Fix
UnboundLocalErrorwhen joining from a model-less source to a model, e.g.join_from(cte, SomeModel, on=...); the joined instance is stored in the source's row dict, keyed by the model name. BlobField,CompressedFieldand thesqlite_udf.gzip()function encodestrvalues using utf-8 instead ofraw_unicode_escape. Behavior change for non-ASCII strings: characters above the latin-1 range are no longer mangled into literal escape sequences, but blobs written from non-ASCII strings by earlier versions will not compare equal to newly-written ones.
Massive bug hunt and patch release. Should be all set, going to let these fixes simmer for a bit.
