I'm trying to display a dropdown list in my form, from my model 'TipoDocumento' (I need to display the column 'nombre_corto' as a list).
1) My model name is "Cocinera", Cocinera inherits from my model "Usuario".
2) "Usuario" inherits it's 'documento' field from my model "Documento".
3) "Documento" model inherits it's 'tipo_documento' field from "TipoDocumento".
But I cannot render 'tipo_documento', as a list, from my 'Cocinera' model through my 'CocineraForm' form. I get an error, detailed at the end.
All my models are in 'nucleo' app. Only the form that gets rendered is in my other app 'app_administrador'.
================================
Nucleo - The app is just named nucleo
================================
MODELS:
Model 'TipoDocumento'
from django.db import models
class TipoDocumento(models.Model):
nombre_corto = models.CharField(blank=False, null=False, max_length=25)
nombre_largo = models.CharField(blank=False, null=False, max_length=100)
def __str__(self):
return self.nombre_corto
Model 'Documento'
class Documento(models.Model):
def __str__(self):
return self.codigo
tipo_documento = models.ForeignKey(TipoDocumento, on_delete=models.SET_NULL, null=True)
codigo = models.CharField(max_length=25)
Model 'Usuario':
class Usuario(models.Model):
class Meta:
abstract = True
nombre = models.CharField(blank=False, null=False, max_length=200)
apellido_paterno = models.CharField(blank=False, null=False, max_length=100)
apellido_materno = models.CharField(blank=True, null=False, max_length=100)
fecha_de_nacimiento = models.DateField(blank=False, null=False)
documento = models.OneToOneField(Documento, on_delete=models.CASCADE, blank=False, null=True)
Model 'Cocinera':
class Cocinera(Usuario):
habilidades = models.ForeignKey(Habilidad, blank=True, null=True)
experiencia_con_mascotas = models.BooleanField(default=False)
def __str__(self):
return self.nombre
================================
app_administrador
================================
My FORM
class CocineraForm(forms.ModelForm):
class Meta:
model = Cocinera
fields = ['nombre', 'apellido_paterno', 'apellido_materno', 'tipo_documento', 'documento', 'fecha_de_nacimiento', 'direccion', 'telefono_o_celular' , 'latitud_y_longitud',
'genero', 'antecedentes_policiales', 'foto']
widgets = {
'fecha_de_nacimiento': DateInput()
}
Related question: According to this Use Django ModelChoice field to create pulldown to lookup table?
I've added:
tipo_documento = forms.ModelChoiceField(queryset=TipoDocumento.objects.all(),
empty_label=None)
But still when I run my app, I get:
File "/home/ogonzales/Escritorio/web_envs/
cocineras_env/lib/python3.5/site-packages/django/forms/models.py",
line 277, in __new__raise FieldError(message)
django.core.exceptions.FieldError: Unknown field(s)
(tipo_documento) specified for Cocinera
Of course you can add an additional field on the form as you already did.
But you are not allowed to add the non-model field 'tipo_documento' in the list of fields, as this refers only to fields defined in your model.
So you should be good to go with:
class CocineraForm(forms.ModelForm):
class Meta:
model = Cocinera
fields = ['nombre', 'apellido_paterno', 'apellido_materno', 'documento',
'fecha_de_nacimiento', 'direccion', 'telefono_o_celular', 'latitud_y_longitud',
'genero', 'antecedentes_policiales', 'foto']
widgets = {
'fecha_de_nacimiento': DateInput()
}
tipo_documento = forms.ModelChoiceField(queryset=TipoDocumento.objects.all(),
empty_label=None)
Note the missing 'tipo_documento' from the fields list.
So, I've found the answer: I needed to work with 2 forms, not just 1, and render both in the 'template'.
Steps:
1.- I needed to create an additional form "DocumentoForm", apart from the "CocineraForm".
class CocineraForm(forms.ModelForm):
class Meta:
model = Cocinera
fields = ['nombre', 'apellido_paterno', 'apellido_materno', 'fecha_de_nacimiento', 'direccion', 'telefono_o_celular', 'latitud_y_longitud',
'genero', 'foto']
#New DocumentoForm
class DocumentoForm(forms.ModelForm):
class Meta:
model = Documento
fields = ['tipo_documento', 'codigo']
2.- I needed to validate all fields of both forms. Create a "Documento" instance from the form "DocumentoForm", without saving it to the DB (commit='False'). And I needed to add this 'Documento' instance to the 'cocinera' model as a field. Just here I should save the 'CocinerForm' with '.save()'.
class RegistroView(View):
def get(self, request):
cocinera_form = CocineraForm()
documento_form = DocumentoForm()
context = {'cocinera_form': cocinera_form, 'documento_form': documento_form}
return render(request, 'app_administrador/crear-registro-como-secretaria.html', context)
def post(self, request):
cocinera_form = CocineraForm(request.POST, request.FILES)
documento_form = DocumentoForm(request.POST)
if all((cocinera_form.is_valid(), documento_form.is_valid())):
documento = documento_form.save()
cocinera = cocinera_form.save(commit=False) #Don't save it to the DB. Just store the variable for now.
cocinera.documento = documento #adding documento to 'Cocinera' model through CocineraForm.
cocinera.save()
return HttpResponseRedirect('/')
3.- Work with 2 forms in the template.
<form action="" method="post">
{% csrf_token %}
{{ cocinera_form }}
{{ documento_form }}
</form>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With