Steve, si se refería a usar el tipo ENUM de MySQL, entonces no tiene suerte, hasta donde yo sé, Django no proporciona soporte para eso (esa característica no está disponible en todas las bases de datos compatibles con Django). La respuesta proporcionada por Paul funciona, pero no definirá el tipo en la base de datos.
Como dijo @Carl Meyer en su respuesta, esto NO crea una columna ENUM en la base de datos. Crea una columna VARCHAR o INTEGER, por lo que realmente no responde a la pregunta.
Ariel
¿Puedo agregar la función de opciones con un campo entero? @fulmicoton
Ilyas karim
36
from django.db import models
classEnumField(models.Field):"""
A field class that maps to MySQL's ENUM type.
Usage:
class Card(models.Model):
suit = EnumField(values=('Clubs', 'Diamonds', 'Spades', 'Hearts'))
c = Card()
c.suit = 'Clubs'
c.save()
"""def __init__(self,*args,**kwargs):self.values = kwargs.pop('values')
kwargs['choices']=[(v, v)for v inself.values]
kwargs['default']=self.values[0]super(EnumField,self).__init__(*args,**kwargs)def db_type(self):return"enum({0})".format(','.join("'%s'"% v for v inself.values))
A partir de django 1.2, deberá agregar un segundo parámetro, conexión, a db_type def.
Hans Lawrenz
2
¿Qué pasó con codecatelog entonces? Lokos como si hubiera sido una buena idea ... Ahora obtengo un 404, incluso para la página raíz.
Danny Staple
33
El uso del choicesparámetro no usará el tipo ENUM db; simplemente creará un VARCHAR o INTEGER, dependiendo de si lo usa choicescon CharField o IntegerField. Generalmente, esto está bien. Si es importante para usted que el tipo ENUM se utilice en el nivel de la base de datos, tiene tres opciones:
Use "./manage.py sql appname" para ver el SQL que genera Django, modifíquelo manualmente para usar el tipo ENUM y ejecútelo usted mismo. Si primero crea la tabla manualmente, "./manage.py syncdb" no la alterará.
Si no desea hacer esto manualmente cada vez que genera su base de datos, coloque algo de SQL personalizado en appname / sql / modelname.sql para ejecutar el comando ALTER TABLE apropiado.
Con cualquiera de estas opciones, sería su responsabilidad lidiar con las implicaciones para la portabilidad entre bases de datos. En la opción 2, puede usar SQL personalizado específico del backend de la base de datos para asegurarse de que su ALTER TABLE solo se ejecute en MySQL. En la opción 3, su método db_type necesitaría verificar el motor de la base de datos y establecer el tipo de columna db en un tipo que realmente exista en esa base de datos.
ACTUALIZACIÓN : Dado que el marco de migraciones se agregó en Django 1.7, las opciones 1 y 2 anteriores están completamente obsoletas. La opción 3 siempre fue la mejor opción de todos modos. La nueva versión de las opciones 1/2 implicaría una migración personalizada compleja utilizando SeparateDatabaseAndState, pero realmente desea la opción 3.
Esta es otra forma agradable y fácil de implementar enumeraciones, aunque realmente no guarda enumeraciones en la base de datos.
Sin embargo, le permite hacer referencia a la 'etiqueta' siempre que consulte o especifique valores predeterminados en lugar de la respuesta mejor calificada en la que debe usar el 'valor' (que puede ser un número).
La configuración choicesen el campo permitirá cierta validación en el extremo de Django, pero no definirá ninguna forma de un tipo enumerado en el extremo de la base de datos.
Como han mencionado otros, la solución es especificar db_typeen un campo personalizado.
Si está utilizando un backend SQL (por ejemplo, MySQL), puede hacer esto así:
from django.db import models
classEnumField(models.Field):def __init__(self,*args,**kwargs):
super(EnumField, self).__init__(*args,**kwargs)assert self.choices,"Need choices for enumeration"def db_type(self, connection):ifnot all(isinstance(col, basestring)for col, _ in self.choices):raiseValueError("MySQL ENUM values should be strings")return"ENUM({})".format(','.join("'{}'".format(col)for col, _ in self.choices))classIceCreamFlavor(EnumField, models.CharField):def __init__(self,*args,**kwargs):
flavors =[('chocolate','Chocolate'),('vanilla','Vanilla'),]
super(IceCreamFlavor, self).__init__(*args, choices=flavors,**kwargs)classIceCream(models.Model):
price = models.DecimalField(max_digits=4, decimal_places=2)
flavor =IceCreamFlavor(max_length=20)
Ejecute syncdbe inspeccione su tabla para ver que ENUMse creó correctamente.
mysql> SHOW COLUMNS IN icecream;+--------+-----------------------------+------+-----+---------+----------------+| Field | Type |Null|Key|Default| Extra |+--------+-----------------------------+------+-----+---------+----------------+| id | int(11)| NO | PRI |NULL| auto_increment || price | decimal(4,2)| NO ||NULL||| flavor | enum('chocolate','vanilla')| NO ||NULL||+--------+-----------------------------+------+-----+---------+----------------+
¡Respuesta muy útil! Pero esto no funcionará para PostgreSQL. La razón es que PostgreSQL ENUM no admite valores predeterminados. En PostgreSQL primero tenemos que crear CREATE DOMAIN o CREATE TYPE. Ref . 8.7. Tipos enumerados Probé el truco de @ David y funciona bien con MySQL, pero en PostgrSQL el trabajo termina con un error 'type "enum" does not exist LINE 1: ....tablename" ADD COLUMN "select_user" ENUM('B', ...'.
Grijesh Chauhan
6
Si realmente desea utilizar sus bases de datos, escriba ENUM:
Utilice Django 1.x
Reconozca que su aplicación solo funcionará en algunas bases de datos.
Actualmente hay dos proyectos de github basados en agregarlos, aunque no he investigado exactamente cómo se implementan:
Django-EnumField :
proporciona un campo de modelo Django de enumeración (utilizando IntegerField) con enumeraciones reutilizables y validación de transición.
Django-EnumFields :
este paquete le permite usar enumeraciones reales de Python (estilo PEP435) con Django.
No creo que ninguno use tipos de enumeración DB, pero están en proceso para el primero.
Ahora, tenga en cuenta que no impone las opciones a nivel de base de datos, esto es solo una construcción de Python. Si también desea aplicar esos valores en la base de datos, puede combinarlo con las restricciones de la base de datos:
Respuestas:
De la documentación de Django :
Y define un charfield en su modelo:
Puede hacer lo mismo con los campos enteros si no le gusta tener letras en su base de datos.
En ese caso, vuelva a escribir sus opciones:
fuente
fuente
El uso del
choices
parámetro no usará el tipo ENUM db; simplemente creará un VARCHAR o INTEGER, dependiendo de si lo usachoices
con CharField o IntegerField. Generalmente, esto está bien. Si es importante para usted que el tipo ENUM se utilice en el nivel de la base de datos, tiene tres opciones:Con cualquiera de estas opciones, sería su responsabilidad lidiar con las implicaciones para la portabilidad entre bases de datos. En la opción 2, puede usar SQL personalizado específico del backend de la base de datos para asegurarse de que su ALTER TABLE solo se ejecute en MySQL. En la opción 3, su método db_type necesitaría verificar el motor de la base de datos y establecer el tipo de columna db en un tipo que realmente exista en esa base de datos.
ACTUALIZACIÓN : Dado que el marco de migraciones se agregó en Django 1.7, las opciones 1 y 2 anteriores están completamente obsoletas. La opción 3 siempre fue la mejor opción de todos modos. La nueva versión de las opciones 1/2 implicaría una migración personalizada compleja utilizando
SeparateDatabaseAndState
, pero realmente desea la opción 3.fuente
http://www.b-list.org/weblog/2007/nov/02/handle-choices-right-way/
Esta es otra forma agradable y fácil de implementar enumeraciones, aunque realmente no guarda enumeraciones en la base de datos.
Sin embargo, le permite hacer referencia a la 'etiqueta' siempre que consulte o especifique valores predeterminados en lugar de la respuesta mejor calificada en la que debe usar el 'valor' (que puede ser un número).
fuente
La configuración
choices
en el campo permitirá cierta validación en el extremo de Django, pero no definirá ninguna forma de un tipo enumerado en el extremo de la base de datos.Como han mencionado otros, la solución es especificar
db_type
en un campo personalizado.Si está utilizando un backend SQL (por ejemplo, MySQL), puede hacer esto así:
Ejecute
syncdb
e inspeccione su tabla para ver queENUM
se creó correctamente.fuente
'type "enum" does not exist LINE 1: ....tablename" ADD COLUMN "select_user" ENUM('B', ...'
.Si realmente desea utilizar sus bases de datos, escriba ENUM:
¡Buena suerte!
fuente
Actualmente hay dos proyectos de github basados en agregarlos, aunque no he investigado exactamente cómo se implementan:
proporciona un campo de modelo Django de enumeración (utilizando IntegerField) con enumeraciones reutilizables y validación de transición.
este paquete le permite usar enumeraciones reales de Python (estilo PEP435) con Django.
No creo que ninguno use tipos de enumeración DB, pero están en proceso para el primero.
fuente
Django 3.0 tiene soporte incorporado para Enums
De la documentación :
Ahora, tenga en cuenta que no impone las opciones a nivel de base de datos, esto es solo una construcción de Python. Si también desea aplicar esos valores en la base de datos, puede combinarlo con las restricciones de la base de datos:
fuente
En la parte superior de su archivo models.py, agregue esta línea después de realizar sus importaciones:
fuente