I want to create a dropdown Course
of Trainee where only options of values in CourseName
of Course model would be shown. Currently I have tried some soulutions after browsing. But its not working. My course dropdown disappeared after editing in forms.py. If i remove this line
Course = forms.ChoiceField(widget=forms.Select(attrs={'class':'col-sm-4'}), choices=course_obj.get_course_name(), label='Course :')
Then the dropdown would show but with no options
model.py
class Course(models.Model):
CourseID = models.AutoField(primary_key=True)
CourseName = models.CharField(max_length=20)
class Meta():
db_table = "Courses"
def get_course_name(self):
return self.CourseName
class Trainee(models.Model):
Name = models.CharField(max_length=50)
Course = models.CharField(max_length=40)
class Meta():
db_table = "Trainee"
forms.py
class TraineeForm(forms.ModelForm):
course_obj = Course()
Name = forms.CharField(widget=forms.TextInput(attrs={'class':'col-sm-4'}), label='Name :')
Course = forms.ChoiceField(widget=forms.Select(attrs={'class':'col-sm-4'}), choices=course_obj.get_course_name(), label='Course :')
........................
edit.html
<form method="post" type="multipart/form-data">
{%csrf_token%}
{% for Name in form.Name %}
<div >
<label >{{ form.Name.label }}</label>
{{ Name }}
</div>
{% endfor %}
{% for Course in form.Course %}
<div >
<label >{{ form.Course.label }}</label>
{{ form.Course }}
</div>
{% endfor %}
CodePudding user response:
===== form.py =====
class TraineeForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(TraineeForm, self).__init__(*args, **kwargs)
self.fields['Course'].widget = forms.Select(choices=Course.objects.values_list('CourseName','CourseName'))
class Meta:
model = Trainee
fields = "__all__"
========= output ===========
CodePudding user response:
While looping a BoundField object - for Name in form.Name
and for Course in form.Course
in your case, Django loop through its sub widgets. A CharField has one sub widget, which is its self. A ChoiceField has as many sub widgets as its options, which is zero in your case. This is why your page rendered like that.
According to Django's Doc on choices
attribute of ChoiceField
:
Either an iterable of 2-tuples to use as choices for this field, enumeration choices, or a callable that returns such an iterable. This argument accepts the same formats as the choices argument to a model field. See the model field reference documentation on choices for more details. If the argument is a callable, it is evaluated each time the field’s form is initialized, in addition to during rendering. Defaults to an empty list.
Try
# forms.py
def course_choices():
return [(course.CourseName, course.CourseName) for course in Course.objects.all()]
class TraineeForm(forms.ModelForm):
Name = forms.CharField(widget=forms.TextInput(attrs={'class':'col-sm-4'}), label='Name :')
Course = forms.ChoiceField(widget=forms.Select(attrs={'class':'col-sm-4'}), choices=course_choices, label='Course :')
class Meta:
model = Trainee
fields = ['Name', 'Course']
And then in your template:
<!-- edit.html -->
<form method="post" type="multipart/form-data">
{% csrf_token %}
<div >
<label >{{ form.Name.label }}</label>
{{ Name }}
</div>
<div >
<label >{{ form.Course.label }}</label>
{{ form.Course }}
</div>
</form>