2011-09-06 14 views
5

Estoy guardando datos en un back-end de PostgreSQL a través de Django. Muchos de los campos en mis modelos son DecimalFields configurados arbitrariamente en max_digits y decimales, que corresponden a columnas numéricas en el backend de la base de datos. Los datos en cada columna tienen una precisión (o número de decimales) que no se conoce a priori, y cada dato en una columna dada no necesita tener la misma precisión.Preservando la precisión de salida con Django DecimalField y PostgreSql Campo numérico

Por ejemplo, los argumentos a un modelo pueden ser:

{'dist': Decimal("94.3"), 'dist_e': Decimal("1.2")} 
{'dist': Decimal("117"), 'dist_e': Decimal("4")} 

donde las claves son los nombres de columna de base de datos.

En la salida, necesito conservar y volver a mostrar esos datos con la precisión con la que se leyeron. En otras palabras, después de consultar la base de datos, los datos mostrados deben verse exactamente como los datos que se leyeron , sin ningún 0 final adicional o faltante en los decimales. Sin embargo, cuando se consulta, ya sea en un shell de django o en la interfaz de administración, todos los datos de DecimalField vuelven con muchos 0 finales.

He visto preguntas similares respondidas por valores monetarios, donde la precisión (2 lugares decimales) es conocida y la misma para todos los datos en una columna determinada. Sin embargo, ¿cómo se puede preservar mejor la precisión exacta representada por los valores decimales en Django y los valores numéricos en PostgreSQL cuando la precisión no es la misma y no se conoce de antemano?

EDIT:

Posiblemente una pieza adicional de utilidad de la información: Al ver la tabla a la que se guardan los datos en una Django dbshell, los muchos arrastran 0 de también están presentes. El valor decimal de python aparentemente se convierte al valor de precisión máximo especificado en el archivo models.py al ser guardado en el backend de PostgreSQL.

+0

Si django está alterando sus números, probablemente necesite escribir un Modelode campo personalizado, ya sea por subclases de DecimalField o por completo comenzando desde cero: -/ – Dave

+0

Sí. Desafortunadamente, la respuesta corta a esta pregunta parece ser que Django no (todavía) admite la columna numérica PostgreSQL de precisión no especificada. Tengo un par de soluciones alternativas en mente para esto, y tan pronto como tenga tiempo para formularlo, haré otra pregunta para comentarios/sugerencias sobre ellas. – krosbonz

Respuesta

1

Si necesita una paridad perfecta hacia adelante y hacia atrás, necesitará usar un CharField. Cualquier campo de base de datos basado en números va a interactuar con sus datos multiplicándolo de una u otra forma. Ahora, sé que mencionaste que no puedes saber la longitud de los dígitos de los puntos de datos, y que un CharField requiere algo de longitud. Puede establecerlo arbitrariamente alto (1000, 2000, etc.) o supongo que podría usar un TextField en su lugar.

Sin embargo, con cualquier enfoque, desperdiciará una gran cantidad de recursos de base de datos en la mayoría de los escenarios. Sugiero que modifiques tu enfoque de modo que no importen los ceros adicionales al final (para fines de visualización siempre puedes cortarlos), o tal que la precisión ya no sea arbitraria.

1

Como hace un momento formulé esta pregunta y la respuesta sigue siendo la misma, compartiré lo que encontré en caso de que sea útil para cualquier persona en un puesto similar. Django no tiene la capacidad de aprovechar el tipo de columnas numéricas de PostgreSQL con precisión arbitraria. Para preservar la precisión de visualización de los datos que cargué en mi base de datos, y para poder realizar cálculos matemáticos sobre los valores obtenidos de las consultas de la base de datos sin primero refundir cadenas en tipos decimales de pitón, opté por agregar una columna de precisión extra para cada columna numérica en la base de datos.

El valor de precisión es un número entero que indica cuántos dígitos después del punto decimal se requieren. Al dato 4.350 se le asigna un valor de 3 en su columna de precisión correspondiente. Normalmente, los números enteros (por ejemplo, 2531) tienen una entrada de precisión de 0. Sin embargo, los enteros grandes informados en notación científica se les asigna un número entero negativo para conservar su precisión de visualización.El valor 4.320E+33, por ejemplo, obtiene la entrada de precisión -3. La base de datos reconoce que todos los objetos con valores de precisión negativos deben volver a mostrarse en notación científica.

Esta solución agrega cierta complejidad a la estructura y al código que rodea la base de datos, pero ha demostrado su eficacia. También me permite preservar con precisión la precisión a través de cálculos como la conversión a/desde el registro y los valores lineales.

Cuestiones relacionadas