so I'm working on a django application where I have a model Event. Each Event has some attributes, say one of them is "hostname" (which I will use throughout as an example). I need to implement search functionality where a user can search for all events that has hostname == some_value, e.g. hostname == "myhost.foo.bar".
Now, I wanted to allow the user to select among the valid options (i.e. the hostnames that actually exist in one or more event) in a combobox in the search form, so I use ModelChoiceFields for my form. My subclass of ModelChoiceView, for displaying the correct label:
class HostnameModelChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return obj.host.hostname
My form:
class QueryForm(forms.Form):
hostname = HostnameModelChoiceField(queryset=Event.objects.all(), required=False)
...
However, this gives duplicates because many events may have the same hostname. I attempted using "distinct()" on the queryset but of course that won't work because the objects are distinct (even if the displayed values are not).
So, I tried to instead select only the values I need:
class QueryForm(forms.Form):
hostname = ModelChoiceField(queryset=Event.objects.all().values_list("hostname", "hostname").distinct(), required=False)
But this won't validate! I suspect because the values are not actual Event instances but just string values.
So I tried a regular ChoiceField:
hostname = forms.ChoiceField(choices=Event.objects.all().values_list("hostname", "hostname").distinct(), required=False)
This works, BUT this list is only populated once, so it's not up to date with the database.
So... Is there any good way of solving this problem? To recap the question: HOW do I populate a combo box with the distinct values from one of the fields of a model, and also keeping it in-sync with the database? I would think开发者_C百科 that a ModelChoiceField would be the best bet, if I can get it to validate when using .values(...) or .values_list(...).
Sincerely, Hallgeir
The second way will work, but you need to set the choices on init so its refreshed each time the form is called.
e.g
class QueryForm(forms.Form):
hostname = forms.ChoiceField(choices=[], required=False)
def __init__(self, *args, **kwargs):
super(QueryForm, self).__init__(*args, **kwargs)
self.fields['hostname'].choices = Event.objects.all().values_list("hostname","hostname").distinct()
精彩评论