| 22 | |
| 23 | |
| 24 | class JSONField(CheckFieldDefaultMixin, Field): |
| 25 | empty_strings_allowed = False |
| 26 | description = _("A JSON object") |
| 27 | default_error_messages = { |
| 28 | "invalid": _("Value must be valid JSON."), |
| 29 | } |
| 30 | _default_hint = ("dict", "{}") |
| 31 | |
| 32 | def __init__( |
| 33 | self, |
| 34 | verbose_name=None, |
| 35 | name=None, |
| 36 | encoder=None, |
| 37 | decoder=None, |
| 38 | **kwargs, |
| 39 | ): |
| 40 | if encoder and not callable(encoder): |
| 41 | raise ValueError("The encoder parameter must be a callable object.") |
| 42 | if decoder and not callable(decoder): |
| 43 | raise ValueError("The decoder parameter must be a callable object.") |
| 44 | self.encoder = encoder |
| 45 | self.decoder = decoder |
| 46 | super().__init__(verbose_name, name, **kwargs) |
| 47 | |
| 48 | def check(self, **kwargs): |
| 49 | errors = super().check(**kwargs) |
| 50 | databases = kwargs.get("databases") or [] |
| 51 | errors.extend(self._check_supported(databases)) |
| 52 | return errors |
| 53 | |
| 54 | def _check_supported(self, databases): |
| 55 | errors = [] |
| 56 | for db in databases: |
| 57 | if not router.allow_migrate_model(db, self.model): |
| 58 | continue |
| 59 | connection = connections[db] |
| 60 | if ( |
| 61 | self.model._meta.required_db_vendor |
| 62 | and self.model._meta.required_db_vendor != connection.vendor |
| 63 | ): |
| 64 | continue |
| 65 | if not ( |
| 66 | "supports_json_field" in self.model._meta.required_db_features |
| 67 | or connection.features.supports_json_field |
| 68 | ): |
| 69 | errors.append( |
| 70 | checks.Error( |
| 71 | "%s does not support JSONFields." % connection.display_name, |
| 72 | obj=self.model, |
| 73 | id="fields.E180", |
| 74 | ) |
| 75 | ) |
| 76 | return errors |
| 77 | |
| 78 | def deconstruct(self): |
| 79 | name, path, args, kwargs = super().deconstruct() |
| 80 | if self.encoder is not None: |
| 81 | kwargs["encoder"] = self.encoder |
no outgoing calls