Repository navigation
What's Changed
Added
Q.__bool__()soQobjects with no filters/children (including nested emptyQchildren) are falsy. (#2227)- PostgreSQL
passwordcredential now accepts a sync or async callable, resolved once per new connection, to support short-lived credentials such as AWS RDS/Aurora IAM tokens and Azure Entra ID tokens. (#2261)
Changed
tortoise.contrib.starlettenow only supports Starlette 1.0+ (This does not affect FastAPI users; you can continue using FastAPI with any version of Starlette). (#2282)
Fixed
- Aggregates now apply
_filterwhen the aggregated argument is an F() or a combined expression (e.g.Sum(F("price") * F("qty"), _filter=Q(status="paid"))). Previously the filter was silently dropped and every row was aggregated. (#2290) - Negating an already negated Q now cancels out: ~~Q(...) and .exclude(~Q(...)) used to keep a single NOT, so they returned the rows the caller meant to drop. (#2291)
- PostgreSQL and Oracle
RemoveIndex/ partialRemoveConstraintnow schema-qualifyDROP INDEX, so indexes on models withMeta.schemacan be dropped when they are not on the connectionsearch_path. (#2288) ForeignKeyField/OneToOneFieldno longer lose a declaredsource_fieldwhen deconstructed.makemigrationswrote the generated<field>_idbacking field name as the column name, so a migrated schema disagreed withgenerate_schemas()and neither path reported an error. (#2284)QuerySet.distinct().count()no longer counts rows duplicated by a join (e.g. filtering on a m2m relation); it now counts distinct primary keys and matches the number of rows the query returns. (#2255)DecimalFieldno longer strips the scale it just applied:to_python_value()called.normalize()immediately after.quantize(), so aDecimalField(max_digits=12, decimal_places=2)holding100.00came back asDecimal('1E+2')and rendered as1E+2in strings, f-strings and JSON. (#2271)- BlackSheep:
register_tortoisenow enables the global connection fallback, so database access works when BlackSheep runs handlers in tasks other than the one that initialized the ORM. (#2248) - fix(queryset): support DELETE/UPDATE with filters on related fields. (#2269)
- Fix naive DatetimeField timezone drift. (#2277)
- A model with its own
Metanow inheritsMeta.orderingfrom its abstract base model when it does not define its own. (#2236) - The return type hint for
IntEnumField/CharEnumFieldis nowtortoise.fields.Field[EnumType]instead ofEnumType. (#2243) - Make EmailValidator allowed_domains actually restrict domains. (#2252)
AlterModelOptionsnow clears options that were removed from the model, instead of only merging in the ones that remain; removing a model docstring no longer makesmakemigrationsregenerate the same migration on every run. (#2279)Model.update_or_create()now applies the caller's defaults after losing a concurrent insert, re-reading the current row through the existing transactional update path. Creation is attempted at most twice, with a final locked read after the last conflict; repeated concurrent deletions that exhaust recovery raiseOperationalErrorrather than retrying indefinitely. (#2276)- psycopg: the connection pool now validates a connection on checkout, so one silently dropped by the network while idle (a firewall or load balancer closing it, a DB restart, ...) gets transparently replaced instead of being handed to the caller and failing with
psycopg.OperationalError: the connection is closed. The check is a cheap no-op query on an already-open socket, so the added latency per checkout is negligible next to a real query. (#2285) - Fixed
prefetch_related()on m2m fields ignoringselect_related(),annotate(), andorder_by()applied to the prefetched queryset. (#2205) pydantic_model_creatorno longer raisesTypeErrorfor models with annotations whose origin is not a class, such asLiteral[...]. (#2311)- Filtering by a related model instance on a
ForeignKeyField/OneToOneFielddeclared with a non-primary-keyto_fieldnow uses theto_fieldvalue instead of the instance's primary key, so the generated query targets the correct column. (#2239) - Database URLs with an empty host (e.g.
postgres:///db?host=/var/run/postgresql&user=u) no longer overwritehost/user/passwordgiven in the query string, so unix domain sockets work. (#2313)
New Contributors
- @VladislavYar made their first contribution in #2227
- @mmdverse made their first contribution in #2269
- @Sanjays2402 made their first contribution in #2255
- @TheRodzz made their first contribution in #2277
- @get-bowen made their first contribution in #2261
- @uttam12331 made their first contribution in #2236
- @apoorvdarshan made their first contribution in #2243
- @dylanpulver made their first contribution in #2271
- @TrueFurina made their first contribution in #2263
- @sam-dawnops made their first contribution in #2093
- @edu2004eu made their first contribution in #2280
- @fzlzjerry made their first contribution in #2276
- @TianHengZhuang made their first contribution in #2281
- @weberhyj made their first contribution in #2282
- @aksgupta98 made their first contribution in #2284
- @AdhamKhalifa made their first contribution in #2289
- @RitiGrover made their first contribution in #2285
- @breken-ai made their first contribution in #2291
- @moneebullah25 made their first contribution in #2311
- @AnayGarodia made their first contribution in #2239
- @VanditGupta made their first contribution in #2313
Full Changelog: 1.1.8...1.1.9