2012-05-20 7 views
25

Todos los documentos que he visto implican que puede ser capaz de hacer eso, pero no hay nada oficial/R/T ulong64/uint64 campos w. Hay algunas opciones estándar que parecen bastante prometedoras en este campo:Puede el Django ORM almacenar un entero sin signo de 64 bits (aka ulong64 o uint64) de una manera fiable backend-agnóstico?

  • BigIntegerField ... casi, pero firmado;
  • PositiveIntegerField ... recelo de 32 bits de aspecto; y
  • DecimalField ... un triple fijo representado con un tipo pitón decimal, según the docs - que presumiblemente se convierte en un campo de base de datos análoga pedante y lento cuando socked de distancia, al estilo de la decimal o tipos numéricos PostgreSQL.

... todos los cuales se ven como que podría tienda de una serie así. Excepto que NINGUNO DE ELLOS SE COMPROMETERÁ, al igual que todos los personajes rom-com interpretados por Hugh Grant.

Mi criterio principal es que funciona con los back-end compatibles de Django, sin ningún tipo de if postgresql (...) elif mysql (...) tipo de sin sentido especial. Después de eso, existe la necesidad de velocidad, esto es para un campo de modelo en una aplicación de base de datos visual que indexará datos derivados de imágenes (p. Ej., Hashes perceptuales y funciones de punto clave extraídas), permitiendo ordenar y agrupar por el contenido de esas imágenes .

Por lo tanto: ¿hay una buena extensión de Django o una aplicación que proporciona algún tipo de PositiveBigIntegerField que se adapte a mis propósitos?

Y, salvo eso: si hay una manera simple y confiable de utilizar stock ORM de Django para almacenar ints sin firmar de 64 bits, me gustaría saberlo. Mira, no soy un genio binario; Tengo que hacer un complemento de dos en papel, así que si este método tuyo implica algún truco de cambio de bit, no dudes en explicar lo que es, incluso si te parece obvio. Gracias por adelantado.

+5

1 de 'al igual que cada personaje de comedia romántica interpretada por Hugh Grant' me hizo reír en una mañana triste y húmedo. –

Respuesta

17

Aunque no he probado, pero es posible que desee simplemente subclase BigIntegerField. El original BigIntegerField parece que (source here):

class BigIntegerField(IntegerField): 
    empty_strings_allowed = False 
    description = _("Big (8 byte) integer") 
    MAX_BIGINT = 9223372036854775807 

    def get_internal_type(self): 
     return "BigIntegerField" 

    def formfield(self, **kwargs): 
     defaults = {'min_value': -BigIntegerField.MAX_BIGINT - 1, 
        'max_value': BigIntegerField.MAX_BIGINT} 
     defaults.update(kwargs) 
     return super(BigIntegerField, self).formfield(**defaults) 

Derivado PositiveBigIntegerField de mayo es el siguiente:

class PositiveBigIntegerField(BigIntegerField): 
    empty_strings_allowed = False 
    description = _("Big (8 byte) positive integer") 

    def db_type(self, connection): 
     """ 
     Returns MySQL-specific column data type. Make additional checks 
     to support other backends. 
     """ 
     return 'bigint UNSIGNED' 

    def formfield(self, **kwargs): 
     defaults = {'min_value': 0, 
        'max_value': BigIntegerField.MAX_BIGINT * 2 - 1} 
     defaults.update(kwargs) 
     return super(PositiveBigIntegerField, self).formfield(**defaults) 

Aunque usted debe probarlo a fondo, antes de usarlo. Si lo hace, por favor, compartir los resultados :)

EDIT:

que se perdió una cosa - la representación base de datos interna. Esto se basa en el valor devuelto por get_internal_type() y la definición del tipo de columna se almacena, por ejemplo. here en el caso de MySQL backend y determinó here. Parece que sobrescribir db_type() le dará control sobre cómo se representa el campo en la base de datos. Sin embargo, deberá encontrar una forma de devolver el valor específico de DBMS en db_type() marcando connection argumento.

+1

Guau, eso parece demasiado bueno para ser cierto, por así decirlo: no estoy demasiado preocupado por la validación de la entrada humana a través de 'FormField' (ya que este dato proviene de una función de análisis de imágenes) y si quitas esas cosas, nos queda el texto 'description', el atributo' MAX_BIGINT' y la especificación 'get_internal_type' ... que ninguna de esas adiciones permite a la subclase decirle al ORM cómo tratarlo como un uint64. Bien podría estar equivocado, si me falta algo aquí con alguno de estos, házmelo saber. – fish2000

+1

@ fish2000: Tenías razón, mira mi edición. La parte que me faltaba era 'db_field()' que pretendía devolver el tipo específico de DBMS basado en el tipo interno devuelto por 'get_internal_type()' y buscado en el diccionario 'data_types' específico de DBMS (visto [aquí] (https: //github.com/django/django/blob/master/django/db/backends/mysql/creation.py#L8)). ¿Soluciona tu problema ahora? – Tadeck

+0

¡Agradable! Es bueno saber dónde guarda el ORM su montón de fragmentos de código SQL patentados. No me había encontrado con eso antes y es lo que se necesita para implementar los métodos 'get_internal_type()' con la misma lógica específica de proveedor que Django. sí mismo. Ese es un gran consejo, ¡gracias! – fish2000

Cuestiones relacionadas