Opened 4 years ago

Closed 4 years ago

#24277 closed Cleanup/optimization (fixed)

Passing a dict with 2 keys to a queryset filter passes erroneously.

Reported by: Keryn Knight Owned by: alexandrinaw
Component: Database layer (models, ORM) Version: master
Severity: Normal Keywords:
Cc: django@…, Nina Zakharenko, alexandrinaw Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description

It's reasonably common to do this:

kws = {'first_name': 'test', 'is_superuser': False}
get_user_model().objects.filter(**kws)

when building up a set of queryset filters, at least if you don't need to introduce ORs (via Q()).

However, if you forget, or accidentally don't star-expand the dictionary:

get_user_model().objects.filter(kws)

You instead get back a queryset with the wrong SQL applied, specifically, above it yields WHERE first_name = 'is_superuser', though that may be a function of the relative stableness of dicts on Python2.

This is in contrast to if your kws dict contains 1, or 3+ keys, which correctly error loudly and let you know you screwed up, yielding either:

ValueError: need more than 1 value to unpack
ValueError: too many values to unpack (expected 2)

Or if you're lucky, and the get_prep_lookup can figure out you've been silly:

# using kws = {'id': 1, 'is_superuser': False}
ValueError: invalid literal for int() with base 10: 'is_superuser'

(This last is a relatively recent addition in master, as far as I can tell, having just pulled up to date from just after 1.8a I think)

The issue itself stems from Query.build_filter, and the specific line which causes the problem I think would survive the changes being made in #24267.

Change History (7)

comment:1 Changed 4 years ago by Anssi Kääriäinen

Triage Stage: UnreviewedAccepted

Agreed that it would be better to error out in this case.

Note that the behavior has been there forever (at least from 1.0 days, see https://github.com/django/django/blob/stable/1.0.x/django/db/models/sql/query.py#L1155)

comment:2 Changed 4 years ago by Nina Zakharenko

Cc: Nina Zakharenko added
Owner: changed from nobody to Nina Zakharenko
Status: newassigned

comment:3 Changed 4 years ago by alexandrinaw

Cc: alexandrinaw added
Owner: changed from Nina Zakharenko to alexandrinaw

comment:4 Changed 4 years ago by alexandrinaw

Has patch: set

comment:5 Changed 4 years ago by Tim Graham

Patch needs improvement: set

Left minor comments for improvement.

comment:6 Changed 4 years ago by alexandrinaw

Triage Stage: AcceptedReady for checkin

comment:7 Changed 4 years ago by Tim Graham <timograham@…>

Resolution: fixed
Status: assignedclosed

In 99d40c6:

Fixed #24277 -- Added exception when dict used in QuerySet filtering

Note: See TracTickets for help on using tickets.
Back to Top