Siam
Siam

Reputation: 17

Dynamic Dropdown values django

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" class="form-group" type="multipart/form-data">
        {%csrf_token%}

        {% for Name in form.Name %}
        <div class="form-group row">
            <label class="col-sm-3 col-form-label">{{ form.Name.label }}</label>
            {{ Name }}

        </div>
        {% endfor %}

        {% for Course in form.Course %}
        <div class="form-group row">
            <label class="col-sm-3 col-form-label">{{ form.Course.label }}</label>
            {{ form.Course }}

        </div>
        {% endfor %}

The Page appears like this enter image description here

Upvotes: 0

Views: 484

Answers (2)

Ezon Zhao
Ezon Zhao

Reputation: 771

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" class="form-group" type="multipart/form-data">
    {% csrf_token %}

    <div class="form-group row">
        <label class="col-sm-3 col-form-label">{{ form.Name.label }}</label>
        {{ Name }}
    </div>

    <div class="form-group row">
        <label class="col-sm-3 col-form-label">{{ form.Course.label }}</label>
        {{ form.Course }}
    </div>
</form>

Upvotes: 1

Mahammadhusain kadiwala
Mahammadhusain kadiwala

Reputation: 3625

===== 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 ===========

enter image description here

Upvotes: 1

Related Questions