Django ModelChoiceField using distinct values from one model attribute

不羁岁月 提交于 2019-12-22 09:31:39

问题


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 that a ModelChoiceField would be the best bet, if I can get it to validate when using .values(...) or .values_list(...).

Sincerely, Hallgeir


回答1:


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()


来源:https://stackoverflow.com/questions/6707991/django-modelchoicefield-using-distinct-values-from-one-model-attribute

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!