#34435: JSONField with string default raises fields.E010 warning.
--------------------------------------+------------------------------------
Reporter: Tobias Krönke | Owner: stimver
Type: Bug | Status: assigned
Component: Core (System checks) | Version: 4.1
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
--------------------------------------+------------------------------------
Comment (by Sage Abdullah):
Replying to [comment:6 Tobias Krönke]:
> That's a good question, because python offers no simple check a la
`ismutable(x)`. It would be easy to just do an additional check like
`isinstance(x, (bool, int, float, tuple, str, frozenset, decimal, complex,
bytes))`, if you can live with the "danger" of users sub-classing those
types and making them mutable. But I guess those can't be helped with this
check.
Strict (without subclasses) `isinstance` checking can be done using
`type(x) in (bool, int, float, tuple, str, ...)`.
Anyway, I'm convinced this is more of a documentation than an
implementation issue. I'll explain below. Buckle up, it's story time!
`JSONField`, `HStoreField`, and `ArrayField` never supported non-callable
defaults as of https://github.com/django/django/pull/8930, when
`JSONField` was still `django.contrib.postgres.fields.JSONField`.
When I started working on the new `django.db.models.JSONField`, I tried
changing this behaviour to support using non-callable defaults because the
base [https://docs.djangoproject.com/en/dev/ref/models/fields/#default
Field.default] documentation (which in theory is applicable to all fields
in `django.db.models`), says `"The default value for the field. This can
be a value or a callable object."`.
Thus, I initially implemented an `isinstance()` check for this (lost in
time, but remnants can be seen at:
https://github.com/django/django/pull/11452#discussion_r295674504).
During the time where this behaviour change was still in the PR, we added
[https://github.com/django/django/blob/8b1ff0da4b162e87edebd94e61f2cd153e9e159d/docs/ref/models/fields.txt#L1268-L1272
the paragraph (quoted in the first comment)] to the documentation for
`JSONField`'s default, based on a suggestion at:
https://github.com/django/django/pull/11452#discussion_r306186695
However, based on the discussion at
https://github.com/django/django/pull/11452#discussion_r335854274, we
explicitly decided **to keep not supporting non-callable defaults for
`JSONField`**. This leads to https://github.com/django/django/pull/11932,
where `CheckFieldDefaultMixin` is moved to
`django.db.models.fields.mixins` without any behaviour change (i.e. the
default **still has to be a callable**).
The problem is, after that decision was made, we forgot to remove the
paragraph in the documentation, which is no longer correct. I believe the
`fields.E010` check message is the correct behaviour here.
Thus, I propose that we change the documentation instead, from
> If you give the field a `default`, ensure it's an immutable object, such
as a `str`, or a callable object that returns a fresh mutable object each
time, such as `dict` or a function. Providing a mutable default object
like `default={}` or `default=[]` shares the one object between all model
instances.
to something like
> If you give the field a `default`, ensure it is a callable object that
returns a fresh object each time, such as `dict` or a function. Providing
a non-callable default object is not supported because a mutable object
would be shared between all model instances. There is a system check to
ensure that the `default` is a callable.
Maybe wrap it in a `note` or something so that it's more prominent,
because this deviates from the base `Field.default` behaviour.
Hope this helps!
--
Ticket URL: <https://code.djangoproject.com/ticket/34435#comment:7>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/01070187958f6cc9-eec71168-9811-48a0-a4f7-d643e6649caf-000000%40eu-central-1.amazonses.com.