postgres - Auto truncar campos en max_length en Django CharFields
models django unique (4)
Tengo un campo que tiene un conjunto max_length
. Cuando guardo una instancia de modelo, y el valor del campo es mayor que max_length
, Django aplica esa max_length
en el nivel de la base de datos. (Consulte los documentos de Django en los modelos: http://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.CharField.max_length )
Sin embargo, dado que estoy usando Postgres, recibo una excepción DatabaseError
como esta:
DatabaseError: value too long for type character varying(1000)
Preferiría, en cambio, truncar automáticamente el valor (para que no tenga una excepción). Ahora puedo hacerlo manualmente, pero lo que realmente quiero es que todos mis modelos trunquen automáticamente el valor. (No necesariamente de forma inteligente. Simplemente cortarlo en el 999.º personaje está bien).
¿Debo simplemente escribir una clase personalizada que importe de models.Model y anular el método save (), recorrer cada _meta.field, verificar max_length, y luego truncar? Eso parece poco elegante y debe haber una mejor manera.
¿Por qué no usas ModelForm
? ModelForm impone una validación, establece su max_length predeterminado para la propiedad max_length del campo de modelo y form.is_valid()
error de validación adecuado cuando se form.is_valid()
. De esta forma, no tiene que guardar el formulario hasta que se valide el formulario.
O bien, si desea pasar silenciosamente la validación y truncar los trajes mejor para usted, escriba un formulario django simple y escriba un método limpio que trunca la cadena de entrada a max_length y devuelva datos eliminados. Tome los datos de form.cleaned_data
después de validar el formulario y guarde el objeto.
Todos considerando el hecho, los formularios están diseñados para validar datos antes de ir a DB.
¿Por qué no usas un TextField? Del manual:
Para grandes cantidades de texto, use TextField.
Podría crear un campo personalizado que trunca automáticamente el campo (creo que este código debería funcionar, pero vuelva a verificarlo):
class TruncatingCharField(models.CharField):
def get_prep_value(self, value):
value = super(TruncatingCharField,self).get_prep_value(value)
if value:
return value[:self.max_length]
return value
Entonces, en lugar de usar models.CharField
en su archivo models.py
, simplemente usaría TruncatingCharField en su lugar.
get_prep_value
prepara el valor de un campo para la inserción en la base de datos, por lo que es el lugar ideal para truncar.
Eso parece poco elegante y debe haber una mejor manera.
La única razón por la que el comportamiento truncado ocurre en primer lugar es porque MySQL no se adhirió al estándar SQL. El lanzamiento de una excepción es la respuesta correcta al intentar INSERTAR una cadena en un campo VARCHAR que no es lo suficientemente ancho como para contenerla. MySQL trunca y se inserta en su lugar.
Si quiere corromper sus datos en silencio, tendrá que hacerlo de forma manual de alguna manera: PostgreSQL nunca lo hará por usted.