While most backends will propagate derived table ordering as long as
the outer query doesn't perform additional processing the SQL specs
doesn't explicitly state the ordering must be maintained.
A more in-depth solution is likely to make sure that we always GROUP BY
selected annotations or revisit how we use Query.exists() in the Exists
expression but that requires extra work that isn't suitable for a
backport.
Regression in e5a92d400a.
Thanks Fernando Flores Villaça for the report.
Made template commands look up formatters before writing files.
This makes sure files included in the template are not identified
as executable formatter commands, even in case the template is
rendered into the system path (as might easily happen on Windows,
where the current directory is on the system path by default).
While at it, Warned about trusting custom templates for
startapp/startproject.
Thanks Trung Pham of Viettel Cyber Security for reporting the issue,
Django Security Team for discussions, and Adam Johnson and
Carlton Gibson for reviews.
Models that use SET, SET_NULL, and SET_DEFAULT as on_delete handler
don't have to fetch objects for the sole purpose of passing them back to
a follow up UPDATE query filtered by the retrieved objects primary key.
This was achieved by flagging SET handlers as _lazy_ and having the
collector logic defer object collections until the last minute. This
should ensure that the rare cases where custom on_delete handlers are
defined remain uncalled when when dealing with an empty collection of
instances.
This reduces the number queries required to apply SET handlers from
2 to 1 where the remaining UPDATE use the same predicate as the non
removed SELECT query.
In a lot of ways this is similar to the fast-delete optimization that
was added in #18676 but for updates this time. The conditions only
happen to be simpler in this case because SET handlers are always
terminal. They never cascade to more deletes that can be combined.
Thanks Renan GEHAN for the report.
Selected rows where not highlighted when returning to the change-list
after clicking "No, take me back" on the deletion confirmation page.
This commit uses the CSS :has() pseudo-class to apply the highlight
without requiring the .selected class, which is added by JavaScript
on the click event.
Once all supported browsers have :has() available, the .selected
selector and the JavaScript to add the class can be removed.
Co-authored-by: Carlton Gibson <carlton.gibson@noumenal.es>
Adds support for joint predicates against window annotations through
subquery wrapping while maintaining errors for disjointed filter
attempts.
The "qualify" wording was used to refer to predicates against window
annotations as it's the name of a specialized Snowflake extension to
SQL that is to window functions what HAVING is to aggregates.
While not complete the implementation should cover most of the common
use cases for filtering against window functions without requiring
the complex subquery pushdown and predicate re-aliasing machinery to
deal with disjointed predicates against columns, aggregates, and window
functions.
A complete disjointed filtering implementation should likely be
deferred until proper QUALIFY support lands or the ORM gains a proper
subquery pushdown interface.
Node.create() which has a compatible signature with Node.__init__()
takes in a single `children` argument rather than relying in unpacking
*args in Q.__init__() which calls Node.__init__().
In addition, we were often needing to unpack iterables into *args and
can instead pass a list direct to Node.create().
- Removed use of Q.deconstruct() in Q._combine().
- Simplified and optimized Q.__invert__() by taking a shallow copy and
swapping the negated attribute only.
- Simplified construction in Q._combine().
- Simplified conditions in Q._combine() as Q.conditional = True the
first isinstance() check is unnecessary.
- Removed copy.copy() branch in Q._combine().
Co-authored-by: Keryn Knight <keryn@kerynknight.com>
This allows the copy.copy() usage in the Q._combine() method to finish
sooner, instead of having to fallback to using the __reduce_ex__(4)
method.
Thia also avoids having to fall into copy.copy() at in Q._combine(),
when combining a Q() with another Q().
Co-authored-by: Keryn Knight <keryn@kerynknight.com>
Node._new_instance() was added in
6dd2b5468f to work around Q.__init__()
having an incompatible signature with Node.__init__().
It was intended as a hook that could be overridden if subclasses needed
to change the behaviour of instantiation of their specialised form of
Node. In practice this doesn't ever seem to have been used for this
purpose and there are very few calls to Node._new_instance() with other
code, e.g. Node.__deepcopy__() calling Node and overriding __class__ as
required.
Rename this to Node.create() to make it a more "official" piece of
private API that we can use to simplify a lot of other areas internally.
The docstring and nearby comment have been reworded to read more
clearly.
Node.subtree_parents was removed in
d3f00bd570. That commit also added
Q.clone() which was identical to WhereNode.clone(), but lacked the
docstring. Q.clone() was later removed in
b454e2cbc9.
- Using the {% plural %} tag.
- Using the |yesno filter.
- Using the |unordered_list filter.
- Unnesting {% if %} where not required.
- Not duplicating {% if %}.