Steve, se você quisesse usar o tipo ENUM MySQL, então você está sem sorte, pelo que eu sei o Django não fornece suporte para isso (esse recurso não está disponível em todos os bancos de dados suportados pelo Django). A resposta fornecida por Paul funciona, mas não definirá o tipo no DB.
Como @Carl Meyer disse em sua resposta, isso NÃO cria uma coluna ENUM no banco de dados. Ele cria uma coluna VARCHAR ou INTEGER, portanto, não responde realmente à pergunta.
Ariel de
Posso adicionar recursos de opções com campo inteiro? @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 do django 1.2, você precisará adicionar um segundo parâmetro, conexão, ao db_type def.
Hans Lawrenz
2
O que aconteceu com codecatelog então? Lokos como se pudesse ter sido uma boa ideia ... Eu recebo um 404 agora - até mesmo para a página raiz.
Danny Staple
33
Usar o choicesparâmetro não usará o tipo de banco de dados ENUM; ele apenas criará um VARCHAR ou INTEGER, dependendo se você usar choicescom CharField ou IntegerField. Geralmente, está tudo bem. Se for importante para você que o tipo ENUM seja usado no nível do banco de dados, você tem três opções:
Use "./manage.py sql appname" para ver o SQL gerado pelo Django, modifique-o manualmente para usar o tipo ENUM e execute-o você mesmo. Se você criar a tabela manualmente primeiro, "./manage.py syncdb" não vai mexer com ela.
Se você não quiser fazer isso manualmente toda vez que gerar seu banco de dados, coloque algum SQL personalizado em appname / sql / modelname.sql para executar o comando ALTER TABLE apropriado.
Com qualquer uma dessas opções, seria sua responsabilidade lidar com as implicações para a portabilidade entre bancos de dados. Na opção 2, você pode usar o SQL personalizado específico do banco de dados para garantir que ALTER TABLE seja executado apenas no MySQL. Na opção 3, seu método db_type precisaria verificar o mecanismo de banco de dados e definir o tipo de coluna db para um tipo que realmente exista nesse banco de dados.
ATUALIZAÇÃO : Como a estrutura de migrações foi adicionada ao Django 1.7, as opções 1 e 2 acima estão totalmente obsoletas. A opção 3 sempre foi a melhor opção de qualquer maneira. A nova versão das opções 1/2 envolveria uma migração personalizada complexa usando SeparateDatabaseAndState- mas você realmente quer a opção 3.
Esta é outra maneira fácil e agradável de implementar enums, embora não salve realmente enums no banco de dados.
No entanto, permite que você faça referência ao 'rótulo' sempre que consultar ou especificar padrões, ao contrário da resposta com melhor classificação, onde você deve usar o 'valor' (que pode ser um número).
A configuração choicesno campo permitirá alguma validação na extremidade do Django, mas não definirá nenhuma forma de um tipo enumerado na extremidade do banco de dados.
Como outros mencionaram, a solução é especificar db_typeem um campo personalizado.
Se estiver usando um back-end SQL (por exemplo, MySQL), você pode fazer isso da seguinte maneira:
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)
Execute syncdbe inspecione sua tabela para ver se o ENUMfoi criado corretamente.
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||+--------+-----------------------------+------+-----+---------+----------------+
Resposta muito útil! Mas isso não funcionará para PostgreSQL. A razão é que PostgreSQL ENUM não suporta o padrão. No PostgreSQL, primeiro temos que criar CREATE DOMAIN ou CREATE TYPE. Reff 8.7. Tipos enumerados Eu tentei o truque de @David e está funcionando bem com o MySQL, mas no PostgrSQL o trabalho acabou com um erro 'type "enum" does not exist LINE 1: ....tablename" ADD COLUMN "select_user" ENUM('B', ...'.
Grijesh Chauhan
6
Se você realmente deseja usar seus bancos de dados tipo ENUM:
Use Django 1.x
Reconhecer que seu aplicativo funcionará apenas em alguns bancos de dados.
Agora, esteja ciente de que ele não impõe as opções em um nível de banco de dados, esta é uma construção apenas do Python. Se você também deseja impor esses valores no banco de dados, pode combinar isso com as restrições do banco de dados:
Respostas:
Da documentação do Django :
E você define um charfield em seu modelo:
Você pode fazer o mesmo com campos inteiros se não quiser ter letras em seu banco de dados.
Nesse caso, reescreva suas escolhas:
fonte
fonte
Usar o
choices
parâmetro não usará o tipo de banco de dados ENUM; ele apenas criará um VARCHAR ou INTEGER, dependendo se você usarchoices
com CharField ou IntegerField. Geralmente, está tudo bem. Se for importante para você que o tipo ENUM seja usado no nível do banco de dados, você tem três opções:Com qualquer uma dessas opções, seria sua responsabilidade lidar com as implicações para a portabilidade entre bancos de dados. Na opção 2, você pode usar o SQL personalizado específico do banco de dados para garantir que ALTER TABLE seja executado apenas no MySQL. Na opção 3, seu método db_type precisaria verificar o mecanismo de banco de dados e definir o tipo de coluna db para um tipo que realmente exista nesse banco de dados.
ATUALIZAÇÃO : Como a estrutura de migrações foi adicionada ao Django 1.7, as opções 1 e 2 acima estão totalmente obsoletas. A opção 3 sempre foi a melhor opção de qualquer maneira. A nova versão das opções 1/2 envolveria uma migração personalizada complexa usando
SeparateDatabaseAndState
- mas você realmente quer a opção 3.fonte
http://www.b-list.org/weblog/2007/nov/02/handle-choices-right-way/
Esta é outra maneira fácil e agradável de implementar enums, embora não salve realmente enums no banco de dados.
No entanto, permite que você faça referência ao 'rótulo' sempre que consultar ou especificar padrões, ao contrário da resposta com melhor classificação, onde você deve usar o 'valor' (que pode ser um número).
fonte
A configuração
choices
no campo permitirá alguma validação na extremidade do Django, mas não definirá nenhuma forma de um tipo enumerado na extremidade do banco de dados.Como outros mencionaram, a solução é especificar
db_type
em um campo personalizado.Se estiver usando um back-end SQL (por exemplo, MySQL), você pode fazer isso da seguinte maneira:
Execute
syncdb
e inspecione sua tabela para ver se oENUM
foi criado corretamente.fonte
'type "enum" does not exist LINE 1: ....tablename" ADD COLUMN "select_user" ENUM('B', ...'
.Se você realmente deseja usar seus bancos de dados tipo ENUM:
Boa sorte!
fonte
Atualmente, existem dois projetos github baseados na adição desses, embora eu não tenha examinado exatamente como eles são implementados:
Fornece um campo de modelo Django de enumeração (usando IntegerField) com enums reutilizáveis e validação de transição.
Este pacote permite que você use enums reais do Python (estilo PEP435) com Django.
Acho que nenhum dos dois usa tipos de enum DB, mas eles estão em andamento para o primeiro.
fonte
Django 3.0 tem suporte integrado para Enums
Da documentação :
Agora, esteja ciente de que ele não impõe as opções em um nível de banco de dados, esta é uma construção apenas do Python. Se você também deseja impor esses valores no banco de dados, pode combinar isso com as restrições do banco de dados:
fonte
No início de seu arquivo models.py, adicione esta linha depois de fazer suas importações:
fonte