#35488: BaseModelFormSet.validate_unique() raises TypeError unhashable type: 'dict'
for JSONFields in a UniqueConstraint
-------------------------------------+-------------------------------------
Reporter: Hanne Moa | Owner: nobody
Type: Bug | Status: new
Component: Forms | Version: 5.0
Severity: Normal | Resolution:
Keywords: JSONField, unique, | Triage Stage: Accepted
formset, json, hashable |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Simon Charette):
* keywords: unique, UniqueConstraint, JSONField, json => JSONField,
unique, formset, json, hashable
Comment:
The problem happens to manifests itself for `JSONField` with
`UniqueConstraint` but it happens for any field with a non-hashable value
that has a unique constraint defined on it.
e.g.
{{{#!python
class FooBar(models.Model):
settings = models.JSONField(unique=True)
}}}
Would exhibit the same problem and the same could be said of `HStoreField`
or other custom fields dealing with `dict`, `set`, and other non-hashable
data types.
Using `django.utils.make_hashable` in `BaseModelFormSet.validate_unique`
seems like a potential low-lift solution but even this function can raise
a `TypeError` if dealing with non-hashable value so maybe we're better off
silencing these `TypeError` and let the model level unique constraint
validation kick in.
I think the latter would be a better approach because uniqueness on such
fields cannot be determined at the Python level. For example, `JSONField`
relies on the `jsonb` type on Postgres so the ordering of keys is not
preserved which means that `{"foo": "bar", "bar": "foo"}` would be
considered equal to `{"bar": "foo", "foo": "bar"}` but not on MySQL which
`json` type is a basically `longtext` with JSON validation and preserves
insertion order.
--
Ticket URL: <
https://code.djangoproject.com/ticket/35488#comment:2>
Django <
https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.