Choice Django - criar choices a partir de um model (ModelChoiceField)
Motivação:
from django.db import models
class Cachorro(models.Model):
RACA_CHOICE = (
('1', 'Pitbull'),
('2', 'Rottweiler'),
('3', 'Vira-lata'),
)
nome = models.CharField(max_length=100)
descricao = models.CharField(max_length=100)
raca = models.CharField(max_length=10, null=False, choices=RACA_CHOICE)
Possuo um formulário de cadastro de cachorros, estou usando uma CHOICE
e, a principio, só temos essas raças atualmente em nosso sistema, porém fico pensando se futuramente, pode ser necessário adicionar uma nova raça ao formulário, então a minha pergunta é, eu consigo atualizar uma CHOICE
em tempo de execução?
Para solucionar este problema é necessário criar um model, e usar esse model como a fonte de dados do nosso campo raca, atribuindo a este campo um ModelChoiceField com um queryset associado.
Vamos então implementar esta funcionalidade
Para isso vai ser necessário criar um formulário baseado em nosso model, para isso eu vou usar a classe ModelForm.
Vamos às mudanças:
from django.db import models
class Cachorro(models.Model):
nome = models.CharField(max_length=100)
descricao = models.CharField(max_length=100)
raca = models.CharField(null=False, max_length=10) #remover o choice aqui
Após remover, devo criar um model que vai representar as minhas opções de raça, para isso vou criar um novo model.
class Raca(models.Model):
nome = models.CharField(max_length=32)
def __str__(self):
return self.nome
Agora devemos aplicar as nossas mudanças, fazendo o makemigrations
e o migrate
.
Isso foi necessário pois agora temos um novo model que vai possuir a mesma finalidade da variável RACA_CHOICE
que tinhamos na nossa primeira versão da implementação.
Para popular as nossas opções, vamos precisar acessar o Django shell para adicionar as os dados necessários (assim vai ser possível ter escolhas no que for renderizado no select/option
[no template html]).
from animal.models import Raca
r = Raca(nome='Pitbull')
r.save()
r1 = Raca(nome='Rottweiler')
r1.save()
r2 = Raca(nome='Vira-lata')
r2.save()
Dessa forma vamos ter renderizado os mesmo dados que tinhamos quando o choice era feito inline na mesma classe.
Então após adicionar os dados vamos criar o formulário.
class CachorroForm(ModelForm):
class Meta:
model = Cachorro
fields = '__all__'
raca = forms.ModelChoiceField(
queryset=Raca.objects.all(),
)
Vou criar um views.py
apenas para renderizar o formulário para exibição:
from django.shortcuts import render
from .models import CachorroForm
def index(request):
form = CachorroForm()
context={
"form": form
}
return render(request, 'animal/index.html', context)
Então teremos renderizado em nosso html o seguinte código:
Mostro em destaque apenas o trecho do html gerado correspondente ao campo raca
:
<select name="raca" required id="id_raca">
<option value="" selected>---------</option>
<option value="1">Pitbull</option>
<option value="2">Rottweiler</option>
<option value="3">Vira-lata</option>
</select>
Com isso terminamos a nossa implementação.
Obrigado