python - En Django 1.9, ¿cuál es la convención para usar JSONField(jsonb postgres nativo)?
postgresql (2)
Django recomienda no usar null=True
para los campos basados en cadenas CharField y TextField para no tener dos valores posibles para "no data" (suponiendo que está permitiendo cadenas vacías con blank=True
). Esto tiene mucho sentido para mí y lo hago en todos mis proyectos.
Django 1.9 presenta JSONField , que utiliza el tipo de datos subyacente jsonb
Postgres. ¿La sugerencia anterior se traslada a JSONField (es decir, se debe usar blank=True
lugar de null=True
)? O, ¿debería null=True
ser usado en su lugar? O, ¿debería ser usado default=dict
su lugar? O, ..? ¿Por qué?
En otras palabras, ¿cuál es la convención para el nuevo JSONField nativo, cuando desea permitir solo un valor "sin datos"? Por favor apoye su respuesta porque hice mucha investigación y no pude encontrar nada oficial. Gracias por adelantado.
La convención implícita en el código de Django parece ser almacenar valores JSON nulos como NULL en lugar de una cadena vacía (como es la convención para el CharField
). Digo esto por lo siguiente:
El empty_strings_allowed
se hereda de Field
en CharField
, y se establece en True
:
django/db/models/fields/__init__.py#L96
class Field(RegisterLookupMixin):
"""Base class for all field types"""
# Designates whether empty strings fundamentally are allowed at the
# database level.
empty_strings_allowed = True
...
JSONField
, sin embargo, lo anula con False
:
django/contrib/postgres/fields/jsonb.py#L13
class JSONField(Field):
empty_strings_allowed = False
...
Esto hace que CharField
''s por defecto sea ""
y JSONField
'' s a None
cuando crea una instancia de un modelo sin pasar explícitamente los valores de estos campos.
django/db/models/fields/init.py#L791
def get_default(self):
"""
Returns the default value for this field.
"""
if self.has_default():
if callable(self.default):
return self.default()
return self.default
if (not self.empty_strings_allowed or (self.null and
not connection.features.interprets_empty_strings_as_nulls)):
return None
return ""
Por lo tanto, si desea que un JSONField
opcional, debe utilizar:
json_field = JSONField(blank=True, null=True)
Si usa solo blank=True
, como lo haría para CharField
, obtendrá un IntegrityError
cuando intente ejecutar MyModel.objects.create(...)
sin pasar un argumento json_field
explícitamente.
Solo quería agregar que debería evitar establecer valores predeterminados en JSONField. Acabo de cometer un error de colegial al configurarlo en {}
. El resultado es que los nuevos objetos recibirán el valor del último objeto si no se estableció explícitamente. Es un comportamiento de Python inherente en el campo JSON, que olvidé considerar.