`values()` returns wrong results when used with list values (JSONField)
If you create model with list in attribute
MockSet(MockModel(list_attr=pytest.pydict()))
then tries to
self.model.objects.filter(id=_id).values("list_attr").first()
> {'list_attr': 'nAvOpyEVAoNGnVZQUqLU'}
if call attribute directly
self.model.objects.filter(id=_id).first().list_attr
it returns full list
['nAvOpyEVAoNGnVZQUqLU', '[email protected]', 3350, datetime.datetime(2002, 6, 18, 3, 24, 51), ...]
for some reason in _item_values method dict transforms into list[dict] here
item_values.append({k: v[i] for k, v in field_buckets.items()})
What is this behavior for?
Thanks for the report. I am currently having trouble following your code and how to reproduce this. Could you please provide some full example test (ideally based upon our own test models) which shows the issue?
Here it is
def test_test(self, faker):
obj_id = faker.random_int()
attr_list = faker.pylist()
qs = MockSet(
MockModel(
id=obj_id,
name="test_values",
attr_list=attr_list,
)
)
assert attr_list == qs.filter(id=obj_id).first().attr_list # passed
assert attr_list == qs.filter(id=obj_id).values("attr_list").first() # failed
Thanks for the example. I just did some quick testing and evaluation and I am a bit unsure here:
- The second assertion will always fail - even when returning the whole list - as
values()yields a dictionary. But yes, after fixing the condition, we still only get the first entry. - Django has no field returning lists by default. Do you use a custom field, a JSON field or something completely different?
You noticed correctly, the second assert returns the dict from which we need to get our array.
I use the standard JSONField. (django.db.models.JSONField)
In this case, we apparently have to extend the existing logic. Feel free to submit a corresponding PR.