An example of a use case would be a callable defined for either model
field's `choices` or `default` that perform an expensive calculation
(either CPI or IO bound), and such callable is wrapped with a caching
decorator. For instance:
{{{
#!python
import functools
@functools.cache
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
@functools.cache
def get_choices():
return {i: fib(i) for i in range(20)}
class Spiral(models.Model):
size = models.IntegerField(choices=get_choices)
}}}
Currently, the error that is raised when generating migrations (assuming
support for callable `choices`), is:
{{{
ValueError: Cannot serialize: <functools._lru_cache_wrapper object at
0x7f819ab3b270>
}}}
Lastly, while I do appreciate this could be done with a custom serializer,
I think it would be of value to provide this in Django core since using
the mentioned the decorators is not (IMHO) a niche case.
--
Ticket URL: <https://code.djangoproject.com/ticket/34822>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* stage: Unreviewed => Accepted
Comment:
Tentatively accepted, let's see how complicated it will be.
--
Ticket URL: <https://code.djangoproject.com/ticket/34822#comment:1>
Comment (by Natalia Bidart):
[https://forum.djangoproject.com/t/callables-for-model-fields-
choices/23654 Related forum post]
--
Ticket URL: <https://code.djangoproject.com/ticket/34822#comment:2>
* owner: nobody => Nick Pope
* status: new => assigned
* has_patch: 0 => 1
Comment:
[https://github.com/django/django/pull/17256 PR]
--
Ticket URL: <https://code.djangoproject.com/ticket/34822#comment:3>
* needs_better_patch: 0 => 1
Comment:
Settings as patch needs improvement due to minor issues with the docs.
--
Ticket URL: <https://code.djangoproject.com/ticket/34822#comment:4>
* needs_better_patch: 1 => 0
--
Ticket URL: <https://code.djangoproject.com/ticket/34822#comment:5>
* stage: Accepted => Ready for checkin
--
Ticket URL: <https://code.djangoproject.com/ticket/34822#comment:6>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"f92e68c30a0d38d25486e3f3cfabe5dfb5961ef7" f92e68c3]:
{{{
#!CommitTicketReference repository=""
revision="f92e68c30a0d38d25486e3f3cfabe5dfb5961ef7"
Fixed #34822 -- Added support for serializing functions decorated with
functools.lru_cache in migrations.
`@functools.cache` and `@functools.lru_cache` return an object of type
`functools._lru_cache_wrapper` which prevented the migrations serializer
from
working. Simply using the existing `FunctionTypeSerializer` for this
additional
type works as expected.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/34822#comment:8>
Comment (by Natalia <124304+nessita@…>):
In [changeset:"c131949e3ebd3b54ee6d4c11239401a215e5cb9b" c131949]:
{{{
#!CommitTicketReference repository=""
revision="c131949e3ebd3b54ee6d4c11239401a215e5cb9b"
Refs #34822 -- Added tests for serializing decorated functions in
migrations.
Functions decorated with a decorator that is properly wrapped, e.g. by
using `@functools.wraps`, are already supported.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/34822#comment:7>
Comment (by Mariusz Felisiak <felisiak.mariusz@…>):
In [changeset:"5f9e5c1b0d5680f793ba7646d52ffab9e2c3623f" 5f9e5c1]:
{{{
#!CommitTicketReference repository=""
revision="5f9e5c1b0d5680f793ba7646d52ffab9e2c3623f"
Refs #34822, Refs #34986 -- Fixed migrations serializer support for
functools.lru_cache().
It turns out that `functools._lru_cache_wrapper` is only a class when
CPython's _functools C module provides it, otherwise it is a function.
PyPy also provides it as a function.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/34822#comment:9>