Propósito e Funcionamento do Parâmetro Choices
O parâmetro choices em campos de modelos Django é projetado para lidar com atributos que possuem um conjunto finito e conhecido de possibilidades. Em vez de permitir valores livres, essa abordagem padroniza o armazenamento e simplifica a exibição de dados na interface da aplicação. Quando um campo da sua aplicação representa uma categoria restrita — como status de ativação, nível de permissão ou tipo de contrato —, o uso de choices é fortemente recomendado.
Em nível de banco de dados, o campo armazena apenas o primeiro valor de cada par definido (geralmente um código ou identificador), enquanto o segundo valor serve como etiqueta legível para o usuário final. Isso mantém os dados otimizados para consultas e relacionamentos, sem sacrificar a legibilidade nas camadas de apresentação.
Estrutura e Definição do Modelo
A definição ocorre através de uma tupla ou lista de tuplas, onde cada item contém dois elementos: o valor armazenado e o nome exibido. A regra fundamental é alinhar o tipo do campo no modelo com o tipo do primeiro elemento da tupla. Se a lista utilizar chaves alfanuméricas, opte por CharField. Se utilizar inteiros, o IntegerField é o mais adequado.
from django.db import models
class PerfilUsuario(models.Model):
nome = models.CharField(max_length=100)
email = models.EmailField(unique=True)
departamento = models.CharField(max_length=50)
NIVEL_ACESSO_CHOICES = [
('ADM', 'Administrador'),
('EDT', 'Editor'),
('VIS', 'Visitante'),
('SUP', 'Suporte'),
]
permissao = models.CharField(
max_length=3,
choices=NIVEL_ACESSO_CHOICES,
default='VIS'
)
Comportamento de Armazenamento e Validação
O Django não impõe restrições rigorosas de validação em nível de banco de dados para os valores fora das opções listadas nos choices. O armazenamento segue estritamente o tipo de campo declarado no modelo. Isso significa que, embora a aplicação espere apenas os códigos definidos em NIVEL_ACESSO_CHOICES, é possível salvar um valor diferente sem gerar exceções imediatas, desde que resepite as limitações do tipo (como tamanho máximo de string ou faixa numérica).
Recuperação dos Valores Exibidos
Para acessar o texto amigável associado ao código salvo, o Django gera automaticamente um método auxiliar para cada campo que utiliza choices. A sintaxe segue o padrão fixo: get_<nome_do_campo>_display().
usuario = PerfilUsuario.objects.get(pk=1)
codigo_salvo = usuario.permissao # Retorna 'ADM'
nome_exibido = usuario.get_permissao_display() # Retorna 'Administrador'
Caso o valor armazenado não faça parte da tupla de escolhas definida no modelo, o método retornará exatamente o valor bruto contido no campo, sem lançar erros ou interromper a execução.
Configuração de Ambiente para Testes Unitários
Para validar o comportamento em um script isolado fora do ciclo de requisição do servidor, é necessário configurar o ambiente do Django manualmente antes de importar os modelos. A estrutura básica segue abaixo:
import os
import sys
import django
# Inicialização do ambiente Django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'projeto_principal.settings')
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
django.setup()
from sistemas_rh.models import PerfilUsuario
# Criação de registros de teste
PerfilUsuario.objects.create(
nome='Ana Silva',
email='ana@empresa.com',
departamento='TI',
permissao='ADM'
)
PerfilUsuario.objects.create(
nome='Carlos Mendes',
email='carlos@empresa.com',
departamento='RH',
permissao='RH' # Valor propositalmente fora da lista NIVEL_ACESSO_CHOICES
)
# Verificação e iteração sobre os dados
for reg in PerfilUsuario.objects.all():
print(f"Registro: {reg.nome} | Código: {reg.permissao} | Exibição: {reg.get_permissao_display()}")
A execução do script demonstrará que o Django persiste ambos os valores corretamente. Ao chamar o método de exibição, o primeiro registro retornará o texto correspondente, enquanto o segundo retornará a string RH conforme armazenada, validando a flexibilidade do ORM quanto a valores não mapeados.