Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#32898 closed New feature (wontfix)

get_or_create() with filter() has surprising behaviour

Reported by: Jamie Cockburn Owned by: nobody
Component: Database layer (models, ORM) Version: 3.2
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

This documentation:
https://docs.djangoproject.com/en/3.2/ref/models/querysets/#get-or-create

That doc says you can combine filter() with get_or_create(). Great!

But the resulting behaviour is somewhat surprising.

Given the following model:

class A(models.Model):
    a = models.CharField()
    b = models.CharField()

I would expect that the following two lines would be fuctionally equivalent:

A.objects.get_or_create(a="something", b="another")
A.objects.filter(a="something").get_or_create(b="another")

If an instance {"a": "something", "b": "another"} already exists in the database then they are equivalent.

If the instance does not exist, the filter().get_or_create() version will create an instance {"a": "", "b": "another"}, throwing away the kwargs passed to filter().

By example:

# create instance
o, c = A.objects.get_or_create(a='something', b="another")
print(o.a, o.b, c)

# find it with filter
o, c = A.objects.filter(a='something').get_or_create(b="another")
print(o.a, o.b, c)

# delete it again
A.objects.all().delete()

# create it with filter
o, c = A.objects.filter(a='something').get_or_create(b="another")
print(o.a, o.b, c)

Will output:

('something', 'another', True)
('something', 'another', False)
('', 'another', True)

This seems rather inconsistent, and should at least be flagged in the docs.

Change History (2)

comment:1 by Mariusz Felisiak, 3 years ago

Resolution: wontfix
Status: newclosed

Thanks for this report, however I don't see anything surprising or confusing in the current behavior, implicit parameters passing would be really unexpected. I also don't see much value in clarifying that parameters are no passed implicitly. You can start a discussion on DevelopersMailingList if you don't agree.

comment:2 by Mariusz Felisiak, 3 years ago

Component: UncategorizedDatabase layer (models, ORM)
Type: UncategorizedNew feature
Note: See TracTickets for help on using tickets.
Back to Top