[Django] #26638: Allow callable in defaults argument for QuerySet.get_or_create

63 views
Skip to first unread message

Django

unread,
May 19, 2016, 10:55:46 AM5/19/16
to django-...@googlegroups.com
#26638: Allow callable in defaults argument for QuerySet.get_or_create
----------------------------------------------+--------------------
Reporter: mlorant | Owner: nobody
Type: New feature | Status: new
Component: Database layer (models, ORM) | Version: master
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 1 | UI/UX: 0
----------------------------------------------+--------------------
It would be nice if `get_or_create` handles callable in the `defaults`
parameter so the defaults value are not computed at each selection.
Indeed, if your default values for insertion contains selection of related
object or any long computation, it is done at each call, even if the
object can be retrieved without insertion (and so the defaults parameter
is not used).

In term of code, I would like to do something like this:

{{{
SomeObject.objects.get_or_create(
key1=value1,
key2=value2,
defaults={
'key3': long_processing_to_get_default(),
# or even
'key3': lambda: OtherModel.objects.get(pk=request.some_value)
}
)
}}}


For backward-compatibility and ease of writing, it should still accept
values that are not callables. See the patch attached (unit tests are
missing so it is not complete!)

--
Ticket URL: <https://code.djangoproject.com/ticket/26638>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
May 19, 2016, 10:56:05 AM5/19/16
to django-...@googlegroups.com
#26638: Allow callable in defaults argument for QuerySet.get_or_create
------------------------------------------+----------------------------

Reporter: mlorant | Owner: nobody
Type: New feature | Status: new
Component: Database layer (models, ORM) | Version: master
Severity: Normal | Resolution:

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Easy pickings: 1
UI/UX: 0 |
------------------------------------------+----------------------------
Changes (by mlorant):

* Attachment "patch26638.txt" added.

Django

unread,
May 19, 2016, 11:02:20 AM5/19/16
to django-...@googlegroups.com
#26638: Allow callable in defaults argument for QuerySet.get_or_create
-------------------------------------+-------------------------------------

Reporter: mlorant | Owner: nobody
Type: New feature | Status: new
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by mlorant):

* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0


Old description:

> It would be nice if `get_or_create` handles callable in the `defaults`
> parameter so the defaults value are not computed at each selection.
> Indeed, if your default values for insertion contains selection of
> related object or any long computation, it is done at each call, even if
> the object can be retrieved without insertion (and so the defaults
> parameter is not used).
>
> In term of code, I would like to do something like this:
>
> {{{
> SomeObject.objects.get_or_create(
> key1=value1,
> key2=value2,
> defaults={
> 'key3': long_processing_to_get_default(),
> # or even
> 'key3': lambda:
> OtherModel.objects.get(pk=request.some_value)
> }
> )
> }}}
>

> For backward-compatibility and ease of writing, it should still accept
> values that are not callables. See the patch attached (unit tests are
> missing so it is not complete!)

New description:

It would be nice if `get_or_create` handles callable in the `defaults`
parameter so the defaults value are not computed at each selection.
Indeed, if your default values for insertion contains selection of related
object or any long computation, it is done at each call, even if the
object can be retrieved without insertion (and so the defaults parameter
is not used).

In term of code, I would like to do something like this:

{{{
SomeObject.objects.get_or_create(
key1=value1,
key2=value2,
defaults={
'key3': lambda: long_processing_to_get_default(),


# or even
'key3': lambda: OtherModel.objects.get(pk=request.some_value)
}
)
}}}


For backward-compatibility and ease of writing, it should still accept
values that are not callables. See the patch attached (unit tests are
missing so it is not complete!)

--

--
Ticket URL: <https://code.djangoproject.com/ticket/26638#comment:1>

Django

unread,
May 19, 2016, 11:06:05 AM5/19/16
to django-...@googlegroups.com
#26638: Allow callable in defaults argument for QuerySet.get_or_create
-------------------------------------+-------------------------------------

Reporter: mlorant | Owner: nobody
Type: New feature | Status: new
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
Description changed by mlorant:

Old description:

> It would be nice if `get_or_create` handles callable in the `defaults`
> parameter so the defaults value are not computed at each selection.
> Indeed, if your default values for insertion contains selection of
> related object or any long computation, it is done at each call, even if
> the object can be retrieved without insertion (and so the defaults
> parameter is not used).
>
> In term of code, I would like to do something like this:
>
> {{{
> SomeObject.objects.get_or_create(
> key1=value1,
> key2=value2,
> defaults={

> 'key3': lambda: long_processing_to_get_default(),


> # or even
> 'key3': lambda:
> OtherModel.objects.get(pk=request.some_value)
> }
> )
> }}}
>

> For backward-compatibility and ease of writing, it should still accept
> values that are not callables. See the patch attached (unit tests are
> missing so it is not complete!)

New description:

It would be nice if `get_or_create` handles callable in the `defaults`
parameter so the defaults value are not computed at each selection.
Indeed, if your default values for insertion contains selection of related
object or any long computation, it is done at each call, even if the
object can be retrieved without insertion (and so the defaults parameter
is not used).

In term of code, I would like to do something like this:

{{{
SomeObject.objects.get_or_create(
key1=value1,
key2=value2,
defaults={
'key3': lambda: long_processing_to_get_default(),


# or even
'key3': lambda: OtherModel.objects.get(pk=request.some_value)
}
)
}}}


For backward-compatibility and ease of writing, it should still accept

values that are not callables. ~~See the patch attached (unit tests are
missing so it is not complete!)~~ My patch is wrong in fact: it computes
the value before the selection and it consider the dict as a whole
callable instead of a single key of the dict... Anyway the implementation
inside the `except DoesNotExist` should be easy :)

--

--
Ticket URL: <https://code.djangoproject.com/ticket/26638#comment:2>

Django

unread,
May 25, 2016, 4:43:35 PM5/25/16
to django-...@googlegroups.com
#26638: Allow callable in defaults argument for QuerySet.get_or_create
-------------------------------------+-------------------------------------

Reporter: mlorant | Owner: nobody
Type: New feature | Status: new
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by ddsnowboard):

I sent a pull request that solves this
(https://github.com/django/django/pull/6650). My understanding of the
ticket is that it should evaluate the callable if and only if the object
needs to be created, and that's what the code does. Is that right?

Also, it passes all the tests under SQLite.

--
Ticket URL: <https://code.djangoproject.com/ticket/26638#comment:3>

Django

unread,
May 25, 2016, 4:45:40 PM5/25/16
to django-...@googlegroups.com
#26638: Allow callable in defaults argument for QuerySet.get_or_create
-------------------------------------+-------------------------------------
Reporter: mlorant | Owner:
| ddsnowboard
Type: New feature | Status: assigned

Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 1 | Needs documentation: 0
Needs tests: 1 | Patch needs improvement: 0

Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by ddsnowboard):

* status: new => assigned
* owner: nobody => ddsnowboard
* has_patch: 0 => 1
* needs_tests: 0 => 1


--
Ticket URL: <https://code.djangoproject.com/ticket/26638#comment:4>

Django

unread,
May 25, 2016, 5:18:25 PM5/25/16
to django-...@googlegroups.com
#26638: Allow callable in defaults argument for QuerySet.get_or_create
-------------------------------------+-------------------------------------
Reporter: mlorant | Owner:
| ddsnowboard
Type: New feature | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed

Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by ddsnowboard):

* needs_tests: 1 => 0


--
Ticket URL: <https://code.djangoproject.com/ticket/26638#comment:5>

Django

unread,
May 26, 2016, 9:43:31 AM5/26/16
to django-...@googlegroups.com
#26638: Allow callable in defaults argument for QuerySet.get_or_create
-------------------------------------+-------------------------------------
Reporter: mlorant | Owner:
| ddsnowboard
Type: New feature | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 1
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by timgraham):

* needs_docs: 0 => 1
* stage: Unreviewed => Accepted


--
Ticket URL: <https://code.djangoproject.com/ticket/26638#comment:6>

Django

unread,
May 28, 2016, 12:34:05 PM5/28/16
to django-...@googlegroups.com
#26638: Allow callable in defaults argument for QuerySet.get_or_create
-------------------------------------+-------------------------------------
Reporter: mlorant | Owner:
| ddsnowboard
Type: New feature | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 1
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by ddsnowboard):

* cc: ddsnowboard (added)


--
Ticket URL: <https://code.djangoproject.com/ticket/26638#comment:7>

Django

unread,
Jun 2, 2016, 1:40:20 PM6/2/16
to django-...@googlegroups.com
#26638: Allow callable in defaults argument for QuerySet.get_or_create
-------------------------------------+-------------------------------------
Reporter: mlorant | Owner:
| ddsnowboard
Type: New feature | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1

Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by timgraham):

* needs_better_patch: 0 => 1
* needs_docs: 1 => 0


Comment:

Left comments for improvement on the PR. Please uncheck "Patch needs
improvement" after updating.

--
Ticket URL: <https://code.djangoproject.com/ticket/26638#comment:8>

Django

unread,
Jun 3, 2016, 10:03:57 AM6/3/16
to django-...@googlegroups.com
#26638: Allow callable in defaults argument for QuerySet.get_or_create
-------------------------------------+-------------------------------------
Reporter: mlorant | Owner:
| ddsnowboard
Type: New feature | Status: closed

Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution: fixed

Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1
Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham <timograham@…>):

* status: assigned => closed
* resolution: => fixed


Comment:

In [changeset:"9899347641b2d3b4457cc99203a2b06504b32a16" 9899347]:
{{{
#!CommitTicketReference repository=""
revision="9899347641b2d3b4457cc99203a2b06504b32a16"
Fixed #26638 -- Allowed callable arguments for
QuerySet.get_or_create()/update_or_create() defaults.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/26638#comment:9>

Reply all
Reply to author
Forward
0 new messages