Malonge
Malonge

Reputation: 2040

Updating Django Forms Dynamically

I have a simple form that provides a drop down menu of all available entries in a django Model.

forms.py

class SampleNameLookupForm(forms.Form):
    #Make a list of sample name options for dropdown menu.
    # Turn that into a list of tuples for ChoiceField.
    samples = Sample.objects.all()
    sample_list = [i.sample_name for i in samples]
    sample_tuple = [(i, i) for i in sample_list]
    Sample_Name = chosenforms.ChosenChoiceField(sample_tuple)

models.py

class Sample(models.Model):
    sample_ID = models.CharField(max_length=20)
    sample_name = models.CharField(max_length=30)

    def __unicode__(self):
        return self.sample_ID

    class Meta:
        ordering = ['id']

When I add a new sample to the model, I can see the new addition when accessing the model in mysql, or in the python manage.py shell, but it does not appear in the chosen field drop down menu.

When I restart the server, the form then reflects the new sample in the drop down menu. How can I update the drop down menu without restarting the server?

I should mention I am just locally hosting and am currently not in production.

Upvotes: 0

Views: 68

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599630

The code needs to be inside the form's __init__ method, rather than directly in the class body, since the method is evaluated on each form instantation, rather than only when the class is defined.

class SampleNameLookupForm(forms.Form):
    def __init__(self):
        #Make a list of sample name options for dropdown menu.
        # Turn that into a list of tuples for ChoiceField.
        samples = Sample.objects.all().values_list('sample_name', flat=True)
        sample_tuple = [(i, i) for i in samples]
        self.fields['Sample_Name'] = chosenforms.ChosenChoiceField(sample_tuple)

Also note, I don't know what ChosenChoiceField is, but the standard Django forms library has a ModelChoiceField which is intended specifically for this use; it takes a queryset argument which is lazily evaluated, and therefore avoids the need for the __init__ stuff.

Upvotes: 2

Related Questions