In that bug, we made sure a proper error was raised when we do
{{{#!python
ChildModel.objects.update(child_field=F('parent_field'))
}}}
We should similarly make sure a proper error is raised when we do
{{{#!python
ChildModel.objects.update(parent_field=F('child_field'))
}}}
With current main, if we add the obvious test
{{{#!diff
diff --git a/tests/expressions/tests.py b/tests/expressions/tests.py
index 33c5189390..0a97d537fe 100644
--- a/tests/expressions/tests.py
+++ b/tests/expressions/tests.py
@@ -318,6 +318,11 @@ class BasicExpressionsTests(TestCase):
with self.assertRaisesMessage(FieldError, msg):
RemoteEmployee.objects.update(adjusted_salary=F('salary') *
5)
+ def test_update_set_inherited_field_from_child(self):
+ msg = 'Joined field references are not permitted in this query'
+ with self.assertRaisesMessage(FieldError, msg):
+ RemoteEmployee.objects.update(salary=F('adjusted_salary') /
5)
+
def test_object_update_unsaved_objects(self):
# F expressions cannot be used to update attributes on objects
which do
# not yet exist in the database
}}}
it fails
{{{
======================================================================
FAIL: test_update_set_inherited_field_from_child
(expressions.tests.BasicExpressionsTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3.9/unittest/case.py", line 59, in testPartExecutor
yield
File "/usr/lib/python3.9/unittest/case.py", line 592, in run
self._callTestMethod(testMethod)
File "/usr/lib/python3.9/unittest/case.py", line 550, in _callTestMethod
method()
File "/home/django/django/tests/expressions/tests.py", line 324, in
test_update_set_inherited_field_from_child
RemoteEmployee.objects.update(salary=F('adjusted_salary') / 5)
File "/usr/lib/python3.9/contextlib.py", line 137, in __exit__
self.gen.throw(typ, value, traceback)
File "/home/django/django/django/test/testcases.py", line 687, in
_assert_raises_or_warns_cm
self.assertIn(expected_message, str(getattr(cm, cm_attr)))
File "/usr/lib/python3.9/unittest/case.py", line 1096, in assertIn
self.fail(self._formatMessage(msg, standardMsg))
File "/usr/lib/python3.9/unittest/case.py", line 668, in fail
raise self.failureException(msg)
AssertionError: 'Joined field references are not permitted in this query'
not found in "Cannot resolve keyword 'adjusted_salary' into field. Choices
are: company_ceo_set, company_point_of_contact_set, firstname, id,
lastname, manager, manager_id, remoteemployee, salary"
----------------------------------------------------------------------
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/33091>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
Comment (by Abhijith Ganesh):
Was this bug patched, I would like to work on this bug and patch it. Would
that be possible @Shai Berger
--
Ticket URL: <https://code.djangoproject.com/ticket/33091#comment:1>
* type: Bug => Cleanup/optimization
* stage: Unreviewed => Accepted
Comment:
Shai, thanks for the report.
Abhijith, feel-free to prepare a patch.
--
Ticket URL: <https://code.djangoproject.com/ticket/33091#comment:2>
Comment (by Abhijith Ganesh):
This is my first attempt of patching an actual django bug, now once i have
made the patch and pushed it to my repository, I should be creating a PR.
Is that all?
--
Ticket URL: <https://code.djangoproject.com/ticket/33091#comment:3>
* owner: nobody => Abhijith Ganesh
* status: new => assigned
Comment:
I am self assigning myself for this issue to avoid confusion.
--
Ticket URL: <https://code.djangoproject.com/ticket/33091#comment:4>
Comment (by Abhijith Ganesh):
For fixing this I should be adding a conditional statement on query.py
file right? and can I get some elaboration as to which method I should be
resolving, I am under the assumption the same resolve method (function)
will be getting a new conditional statement
--
Ticket URL: <https://code.djangoproject.com/ticket/33091#comment:5>
Comment (by Abhijith Ganesh):
{{{#!python
if annotation and not allow_joins:
raise FieldError('Parent field references are not allowed in
this query.')
}}}
Would this be a good fix?
This is my first fix and I am looking forward to learn, thanks in advance.
--
Ticket URL: <https://code.djangoproject.com/ticket/33091#comment:6>
Comment (by Shai Berger):
Hi Abhijith, sorry for failing to respond earlier.
The best answer is, try: I've included in the ticket description a failing
test for it. Add this test, and check if your suggested fix makes it pass
(and doesn't break other tests).
--
Ticket URL: <https://code.djangoproject.com/ticket/33091#comment:7>
Comment (by Bhuvnesh):
I think there is no direct way to get child field from opts of parent
model in inheritance. The value of field is None at
[https://github.com/django/django/blob/9da2210f121085e998dc7cedb783bc4568390b92/django/db/models/sql/query.py#L1631
this part] ,throwing different field error
[https://github.com/django/django/blob/9da2210f121085e998dc7cedb783bc4568390b92/django/db/models/sql/query.py#L1714
here.] Is it the expected behaviour? or we are supposed to get the child
field and later raise field error {{{Joined field references are not
permitted in this query.}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/33091#comment:8>
Comment (by Shai Berger):
Replying to [comment:8 Bhuvnesh]:
> I think there is no direct way to get child field from opts of parent
model in inheritance.
That makes sense
> For the testcase provided by shai the value of field is None at
[https://github.com/django/django/blob/9da2210f121085e998dc7cedb783bc4568390b92/django/db/models/sql/query.py#L1631
this part] ,throwing different field error
[https://github.com/django/django/blob/9da2210f121085e998dc7cedb783bc4568390b92/django/db/models/sql/query.py#L1714
here.] Is it the expected behaviour?
No, that's the bug...
> or we are supposed to get the child field and later raise field error
{{{Joined field references are not permitted in this query.}}}
Yes, basically. Or, putting it another way (given your input): The
{{{update()}}} logic uses the parent model {{{opts}}}, because the fields
to be updated are all from that model; but then it uses the parent model
to resolve all references, and that is wrong if there are expressions
referencing the child model. Or, more succinctly: The move to the parent
model is too early.
--
Ticket URL: <https://code.djangoproject.com/ticket/33091#comment:9>