UpdateQuery.add_update_values always computes "direct" variable as True
For context, I've been messing around with ForeignObject
in an attempt to use correlated subqueries as a join condition. e.g., defining a latest_post
relation field that enables queries like Author.objects.select_related("latest_post")
. Given that the relation is based on a subquery, the field is not concrete, and in testing how the queryset API works with this field, I ran into a confusing condition in QuerySet.update
via the UpdateQuery.add_update_values
method. In short, line 90 computes a direct
variable that always resolves to true. You can verify how the boolean logic resolves with:
class UpdateTests(unittest.TestCase):
def test_direct(self):
testcases = [
(True, True),
(True, False),
(False, True),
(False, False),
]
for auto_created, concrete in testcases:
with self.subTest(auto_created=auto_created, concrete=concrete):
self.assertTrue(not (auto_created and not concrete) or not concrete)
This condition should simplify to not auto_created or concrete or not concrete
to concrete or not concrete
to True
. Digging through the blame, direct was previously provided by the model meta's .get_field_by_name()
, which states "direct is True if the field exists on this model". Without fully understanding the field internals, I assume direct
should have been replaced with just field.concrete
. I'm not sure what the intent was for auto-created fields, but whether it's concrete seems to be the actual relevant bit, not whether it's auto-created.
Change History
(8)
Triage Stage: |
Unreviewed → Accepted
|
Owner: |
set to Ryan P Kilby
|
Status: |
new → assigned
|
Patch needs improvement: |
set
|
Needs tests: |
set
|
Patch needs improvement: |
unset
|
Needs tests: |
unset
|
Triage Stage: |
Accepted → Ready for checkin
|
Resolution: |
→ fixed
|
Status: |
assigned → closed
|
In 11c2c9a: