python json django postgresql jsonb

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.