Home > Net >  Dynamic Dropdown values django
Dynamic Dropdown values django

Time:09-26

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 %}

The Page appears like this enter image description here

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

enter image description here

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>
  • Related