#36607: Improve the documentation by mentioning that "filter(a,b)" may not be the
same as "filter(a).filter(b)" on querysets.
-------------------------------------+-------------------------------------
Reporter: Aaron | Type:
| Uncategorized
Status: new | Component: Database
| layer (models, ORM)
Version: 5.2 | Severity: Normal
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Dear community,
I just got informed about the fact that "filter(a,b)" might not be the
same as
"filter(a).filter(b)". The following example may be useful for
illustrating
this. It uses some code that is inspired by our code and won't run without
context, but I hope it is illustrating enough.
The intend is to filter for MaintenanceOperations. Therefore, we create
one:
{{{#!python
op = MaintenanceOperationFactory()
}}}
These objects are children of the MaintenanceOperation:
{{{#!python
maint_a = UnscheduledMaintenanceFactory(operation=op,
execution_start="2030-03-10T12:00:00Z")
maint_b = UnscheduledMaintenanceFactory(operation=op,
execution_start="2030-05-10T12:00:00Z")
}}}
We construct a first queryset like this:
{{{#!python
qs1 =
MaintenanceOperation.objects.filter(maintenances__execution_start__gt="2030-04-10T12:00:00Z",
maintenances__execution_start__lt="2030-04-20T12:00:00Z",)
}}}
This qs evaluates to: <MaintenanceOperationQuerySet []> (aka the empty
list). This happens because
neither UnscheduledMaintenance meets both criteria. The underlying sql is
this:
{{{#!sql
SELECT "maintenance_maintenanceoperation"."id" FROM
"maintenance_maintenanceoperation" INNER JOIN "maintenance_maintenance" ON
("maintenance_maintenanceoperation"."id" =
"maintenance_maintenance"."operation_id") WHERE
("maintenance_maintenanceoperation"."deleted_at" IS NULL AND
"maintenance_maintenance"."execution_start" > 2030-04-10 12:00:00+00:00
AND
"maintenance_maintenance"."execution_start" < 2030-04-20 12:00:00+00:00)
}}}
To demonstrate the second case, we build the following queryset:
{{{#!python
qs2 = MaintenanceOperation.objects.filter(
maintenances__execution_start__gt="2030-04-10T12:00:00Z",).filter(
maintenances__execution_start__lt="2030-04-20T12:00:00Z",)
}}}
This qs evaluates to:<MaintenanceOperationQuerySet [<MaintenanceOperation:
#1:
beauftragt>]>(This list contains the MaintenanceOperation we created at
the start)
This is different from the first one, because the sql is done with another
join:
{{{#!sql
SELECT "maintenance_maintenanceoperation"."id"
FROM "maintenance_maintenanceoperation" INNER JOIN
"maintenance_maintenance" ON
("maintenance_maintenanceoperation"."id" =
"maintenance_maintenance"."operation_id") INNER JOIN
"maintenance_maintenance"
T3 ON ("maintenance_maintenanceoperation"."id" = T3."operation_id") WHERE
("maintenance_maintenanceoperation"."deleted_at" IS NULL AND
"maintenance_maintenance"."execution_start" > 2030-04-10 12:00:00+00:00
AND
T3."execution_start" < 2030-04-20 12:00:00+00:00)
}}}
I think this should be mentioned in the filter documentation, particularly
in the
section on joining filters. If this is met with approval I am open to
sketching a
suggestion.
--
Ticket URL: <
https://code.djangoproject.com/ticket/36607>
Django <
https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.