Opened 44 hours ago
Last modified 40 hours ago
#36431 new Bug
values() query on ForeignObject discards additional columns
Reported by: | Jacob Walls | Owned by: | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 4.2 |
Severity: | Normal | Keywords: | composite primary key |
Cc: | Simon Charette | Triage Stage: | Accepted |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
For a multi-column field using ForeignObject
as modeled here, .values("user")
will discard columns after the first, and values("user", "integer")
will select the second column of user
into the integer
namespace.
Here's a failing test for tests/composite_pk/test_values.py:
def test_foreign_object_values(self): Comment.objects.create(id=1, user=self.user_1, integer=42) values = list(Comment.objects.values("user", "integer")) self.assertEqual(values[0]["integer"], 42)
====================================================================== FAIL: test_foreign_object_values (composite_pk.test_values.CompositePKValuesTests.test_foreign_object_values) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/.../django/tests/composite_pk/test_values.py", line 217, in test_foreign_object_values self.assertEqual(values[0]["integer"], 42) ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^ AssertionError: 1 != 42
And a similar rough test for foreign_objects/tests.py that fails on Django 4.2, to remove the composite primary key from discussion. (If this model had more fields, this values query would be more realistic):
class ForeignObjectValues(TestCase): def test_foreign_object_values(self): from .models import Customer customer_1 = Customer.objects.create(customer_id=1, company="a") customer_2 = Customer.objects.create(customer_id=1, company="b") company_a_customers = Customer.objects.filter(company="a").values("address", "company") self.assertSequenceEqual( Customer.objects.exclude(company__in=[cust["company"] for cust in company_a_customers]), [customer_2], # Fails, all companies included )
Change History (2)
comment:1 by , 42 hours ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:2 by , 40 hours ago
Cc: | added |
---|
On interesting dilemma we'll have to figure out here is what exactly to return when a foreign object composed of more than one
from_fields
is selected throughvalues
andvalues_list
.With composite primary keys we've made usages of
values("pk")
turned intovalues(Tuple(*pk_field_attnames))
and notvalues(*pk_field_attnames)
so we should be coherent here IMO which means that we likely want something liketests/composite_pk/test_values.py
Post, Tenant, UserIn other words I suggest we double down on making sure references to composite fields (the only two we support today is composite pk and foreign objects with multiple fields) in
values
andvalues_list
return tuples instead of flattening them as we've taken this approach forCompositePrimaryKey
(which is now part of the public API) and thatForeignObject
is still private and has been broken since its introduction in this regard.