﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
32549	Add `Q.empty()` to check for nested empty Q objects like `Q(Q())`	jonathan-golorry	nobody	"Empty Q objects (`Q()` or `~Q()`, etc) evaluate to `False`, but `Q(Q())` evaluates to `True`. This interferes with the shortcut on logical operations involving empty Q objects and can lead to bugs when trying to detect empty operations.
{{{
def q_any(iterable):
    q = Q()
    for element in iterable:
        q |= element
    if q:
        return q
    return Q(pk__in=[])
Item.objects.filter(q_any())  # no items
Item.objects.filter(q_any([Q()]))  # no items
Item.objects.filter(q_any([Q(Q())]))  # all items
}}}

~~Patch https://github.com/django/django/pull/14127 removes empty Q objects from `args` during Q object initialization.~~

Patch https://github.com/django/django/pull/14130 adds `.empty()` for detecting nested empty Q objects and uses that instead of boolean evaluation for shortcutting logical operations between empty Q objects. So `Q(x=1) | Q(Q())` will now shortcut to `Q(x=1)` the same way `Q(x=1) | Q()` does. No simplifying is done during Q object initialization.

This requires https://code.djangoproject.com/ticket/32548 in order to prevent a regression in logical operations between query expressions and empty Q objects."	Cleanup/optimization	closed	Database layer (models, ORM)	dev	Normal	wontfix	Q objects, nested, empty		Unreviewed	1	0	0	0	0	0
