简体   繁体   中英

Django Forms with dynamic field values

First time using Django Forms. I'm stuck trying to get the dropdown choices to reload. My forms.py is below. When the database state changes, the choices do not. I suppose that this is because they are defined at a class level, which means the query happens at initialisation of the module? I've found that the only way to get my dropdowns to update is to restart the webserver.

How can I have the database queries evaluate on every request?

forms.py

from django import forms 
from app.models import Collection, ErrorMessage, Service

class FailureForm(forms.Form):
    collections = [(collection.value,)*2 for collection in Collection.objects.all()]
    error_messages = [(message.value,)*2 for message in ErrorMessage.objects.all()]
    services = [(service.value,)*2 for service in Service.objects.all()]

    collection = forms.CharField(label='collection', max_length=100, widget=forms.Select(choices=collections))
    error_message = forms.CharField(label='error_message', max_length=400, widget=forms.Select(choices=error_messages))
    service = forms.CharField(label='service', max_length=100, widget=forms.Select(choices=services))
class FailureForm(forms.Form):
    collection = forms.ChoiceField(widget=forms.Select, choices=[])
    ... # etc

    def __init__(self, *args, **kwargs):
        super(FailureForm, self).__init__(*args, **kwargs)
        self.fields['collection'].choices = [(collection.value,)*2 for collection in Collection.objects.all()]
        ... # etc

Note: label='collection' is obsolete. It will be "collection" by default. Same with error_message and service

Did some more digging in the documentation and noticed that callables on a ChoiceField are called every initialisation. Therefore, the solution below was I think preferable for me.

class FailureForm(forms.Form):
    collection = forms.ChoiceField(choices=lambda: [(collection.value,)*2 for collection in Collection.objects.all()])
    error_message = forms.ChoiceField(choices=lambda: [(message.value,)*2 for message in ErrorMessage.objects.all()])
    service = forms.ChoiceField(choices=lambda: [(service.value,)*2 for service in Service.objects.all()])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM