Steve, wenn Sie den MySQL ENUM-Typ verwenden wollten, haben Sie Pech, soweit ich weiß, dass Django dies nicht unterstützt (diese Funktion ist nicht in allen von Django unterstützten DBs verfügbar). Die Antwort von Paul funktioniert, definiert jedoch nicht den Typ in der Datenbank.
Wie @Carl Meyer in seiner Antwort sagte, erstellt dies KEINE ENUM-Spalte in der Datenbank. Es wird eine VARCHAR- oder INTEGER-Spalte erstellt, sodass die Frage nicht wirklich beantwortet wird.
Ariel
Kann ich eine Auswahlfunktion mit einem Ganzzahlfeld hinzufügen? @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))
Ab django 1.2 müssen Sie dem db_type def einen zweiten Parameter, connection, hinzufügen.
Hans Lawrenz
2
Was ist dann mit Codecatelog passiert? Lokos wie es hätte eine gute Idee sein können ... Ich bekomme jetzt eine 404 - sogar für die Root-Seite.
Danny Staple
33
Bei Verwendung des choicesParameters wird der ENUM-DB-Typ nicht verwendet. Es wird nur ein VARCHAR oder INTEGER erstellt, je nachdem, ob Sie choicesmit einem CharField oder IntegerField verwenden. Im Allgemeinen ist dies in Ordnung. Wenn es Ihnen wichtig ist, dass der ENUM-Typ auf Datenbankebene verwendet wird, haben Sie drei Möglichkeiten:
Verwenden Sie "./manage.py sql appname", um zu sehen, wie SQL Django generiert wird, ändern Sie es manuell, um den ENUM-Typ zu verwenden, und führen Sie es selbst aus. Wenn Sie die Tabelle zuerst manuell erstellen, wird "./manage.py syncdb" nichts damit anfangen.
Wenn Sie dies nicht jedes Mal manuell tun möchten, wenn Sie Ihre Datenbank generieren, fügen Sie in appname / sql / modelname.sql benutzerdefiniertes SQL ein, um den entsprechenden Befehl ALTER TABLE auszuführen.
Erstellen Sie einen benutzerdefinierten Feldtyp und definieren Sie die Methode db_type entsprechend.
Bei jeder dieser Optionen liegt es in Ihrer Verantwortung, sich mit den Auswirkungen auf die datenbankübergreifende Portabilität zu befassen. In Option 2 können Sie datenbank-backendspezifisches benutzerdefiniertes SQL verwenden, um sicherzustellen, dass ALTER TABLE nur unter MySQL ausgeführt wird. In Option 3 müsste Ihre Methode db_type das Datenbankmodul überprüfen und den Spaltentyp db auf einen Typ setzen, der tatsächlich in dieser Datenbank vorhanden ist.
UPDATE : Da das Migrationsframework in Django 1.7 hinzugefügt wurde, sind die obigen Optionen 1 und 2 völlig veraltet. Option 3 war sowieso immer die beste Option. Die neue Version von Optionen 1/2 würde eine komplexe benutzerdefinierte Migration mit beinhalten SeparateDatabaseAndState- aber Sie möchten wirklich Option 3.
Dies ist eine weitere nette und einfache Möglichkeit, Enums zu implementieren, obwohl Enums nicht wirklich in der Datenbank gespeichert werden.
Sie können jedoch bei jeder Abfrage oder Angabe von Standardeinstellungen auf das 'Label' verweisen, im Gegensatz zu der am besten bewerteten Antwort, bei der Sie den 'Wert' (der eine Zahl sein kann) verwenden müssen.
Die Einstellung choicesauf dem Feld ermöglicht eine gewisse Validierung am Django-Ende, wird dies jedoch nicht tun jede Form eines Aufzählungstypen auf der Datenbank Ende definieren.
Wie andere bereits erwähnt haben, besteht die Lösung darin, anzugeben db_type in einem benutzerdefinierten Feld .
Wenn Sie ein SQL-Backend (z. B. MySQL) verwenden, können Sie dies folgendermaßen tun:
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)
Führen syncdbSie die Tabelle aus und überprüfen Sie sie, um festzustellen, ob die Tabelle ENUMordnungsgemäß erstellt wurde.
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||+--------+-----------------------------+------+-----+---------+----------------+
Sehr hilfreiche Antwort! Dies funktioniert jedoch nicht für PostgreSQL. Der Grund dafür ist, dass PostgreSQL ENUM die Standardeinstellungen nicht unterstützt. In PostgreSQL müssen wir zuerst CREATE DOMAIN oder CREATE TYPE erstellen. Reff 8.7. Aufgezählte Typen Ich habe @ Davids Trick ausprobiert und es funktioniert gut mit MySQL, aber in PostgrSQL endet die Arbeit mit einem Fehler 'type "enum" does not exist LINE 1: ....tablename" ADD COLUMN "select_user" ENUM('B', ...'.
Grijesh Chauhan
6
Wenn Sie Ihre Datenbanken wirklich verwenden möchten, geben Sie ENUM ein:
Verwenden Sie Django 1.x.
Erkennen Sie, dass Ihre Anwendung nur in einigen Datenbanken funktioniert.
Derzeit gibt es zwei Github-Projekte, die auf dem Hinzufügen dieser Projekte basieren, obwohl ich nicht genau untersucht habe, wie sie implementiert sind:
Django-EnumField :
Stellt ein Aufzählungs- (unter Verwendung von IntegerField) mit wiederverwendbaren Aufzählungen und Übergangsvalidierung bereit.
Django-EnumFields : Mit
diesem Paket können Sie echte Python-Enums (PEP435-Stil) mit Django verwenden.
Ich glaube auch nicht, dass DB-Aufzählungstypen verwendet werden, aber sie sind für den ersten in Arbeit .
Beachten Sie nun, dass die Auswahl auf Datenbankebene nicht erzwungen wird. Dies ist nur ein Python-Konstrukt. Wenn Sie diesen Wert auch in der Datenbank erzwingen möchten, können Sie dies mit Datenbankeinschränkungen kombinieren:
Antworten:
Aus der Django-Dokumentation :
Und Sie definieren ein Zeichenfeld in Ihrem Modell:
Sie können dasselbe mit Ganzzahlfeldern tun, wenn Sie keine Buchstaben in Ihrer Datenbank haben möchten.
Schreiben Sie in diesem Fall Ihre Auswahl neu:
quelle
quelle
Bei Verwendung des
choices
Parameters wird der ENUM-DB-Typ nicht verwendet. Es wird nur ein VARCHAR oder INTEGER erstellt, je nachdem, ob Siechoices
mit einem CharField oder IntegerField verwenden. Im Allgemeinen ist dies in Ordnung. Wenn es Ihnen wichtig ist, dass der ENUM-Typ auf Datenbankebene verwendet wird, haben Sie drei Möglichkeiten:Bei jeder dieser Optionen liegt es in Ihrer Verantwortung, sich mit den Auswirkungen auf die datenbankübergreifende Portabilität zu befassen. In Option 2 können Sie datenbank-backendspezifisches benutzerdefiniertes SQL verwenden, um sicherzustellen, dass ALTER TABLE nur unter MySQL ausgeführt wird. In Option 3 müsste Ihre Methode db_type das Datenbankmodul überprüfen und den Spaltentyp db auf einen Typ setzen, der tatsächlich in dieser Datenbank vorhanden ist.
UPDATE : Da das Migrationsframework in Django 1.7 hinzugefügt wurde, sind die obigen Optionen 1 und 2 völlig veraltet. Option 3 war sowieso immer die beste Option. Die neue Version von Optionen 1/2 würde eine komplexe benutzerdefinierte Migration mit beinhalten
SeparateDatabaseAndState
- aber Sie möchten wirklich Option 3.quelle
http://www.b-list.org/weblog/2007/nov/02/handle-choices-right-way/
Dies ist eine weitere nette und einfache Möglichkeit, Enums zu implementieren, obwohl Enums nicht wirklich in der Datenbank gespeichert werden.
Sie können jedoch bei jeder Abfrage oder Angabe von Standardeinstellungen auf das 'Label' verweisen, im Gegensatz zu der am besten bewerteten Antwort, bei der Sie den 'Wert' (der eine Zahl sein kann) verwenden müssen.
quelle
Die Einstellung
choices
auf dem Feld ermöglicht eine gewisse Validierung am Django-Ende, wird dies jedoch nicht tun jede Form eines Aufzählungstypen auf der Datenbank Ende definieren.Wie andere bereits erwähnt haben, besteht die Lösung darin, anzugeben
db_type
in einem benutzerdefinierten Feld .Wenn Sie ein SQL-Backend (z. B. MySQL) verwenden, können Sie dies folgendermaßen tun:
Führen
syncdb
Sie die Tabelle aus und überprüfen Sie sie, um festzustellen, ob die TabelleENUM
ordnungsgemäß erstellt wurde.quelle
'type "enum" does not exist LINE 1: ....tablename" ADD COLUMN "select_user" ENUM('B', ...'
.Wenn Sie Ihre Datenbanken wirklich verwenden möchten, geben Sie ENUM ein:
Viel Glück!
quelle
Derzeit gibt es zwei Github-Projekte, die auf dem Hinzufügen dieser Projekte basieren, obwohl ich nicht genau untersucht habe, wie sie implementiert sind:
Stellt ein Aufzählungs- (unter Verwendung von IntegerField) mit wiederverwendbaren Aufzählungen und Übergangsvalidierung bereit.
diesem Paket können Sie echte Python-Enums (PEP435-Stil) mit Django verwenden.
Ich glaube auch nicht, dass DB-Aufzählungstypen verwendet werden, aber sie sind für den ersten in Arbeit .
quelle
Django 3.0 bietet integrierte Unterstützung für Enums
Aus der Dokumentation :
Beachten Sie nun, dass die Auswahl auf Datenbankebene nicht erzwungen wird. Dies ist nur ein Python-Konstrukt. Wenn Sie diesen Wert auch in der Datenbank erzwingen möchten, können Sie dies mit Datenbankeinschränkungen kombinieren:
quelle
Fügen Sie oben in Ihrer Datei models.py diese Zeile hinzu, nachdem Sie Ihre Importe durchgeführt haben:
quelle