Add "empty" variant to ChoiceField based on model data

I am defining ChoiceField based on model data.

field = forms.ChoiceField(choices=[[r.id, r.name] for r in Model.objects.all()])

      

However, I would like to add my options with empty to select the objects "no". But I cannot find a good way to add this.

All my tests:

field = forms.ChoiceField(choices=[[0, '----------']].extend([[r.id, r.name] for r in Model.objects.all()]))

      

Returns me an error "Invalid object is not duplicate". The only way I've found so far is this:

def append_empty(choices):
    ret = [[0, '----------']]
    for c in choices:
        ret.append(c)
   return ret

      

And when I define my field:

forms.ChoiceField(choices=append_empty([[r.id, r.name] for r in
    Restaurant.objects.all()]), required=False)

      

However, I would like my code to be clean and free of such horrors. Do you have an idea for me?: P Thanks in advance.

+2


source to share


2 answers


Easy answer:

field = forms.ChoiceField(choices=[[0, '----------']] + [[r.id, r.name] for r in Model.objects.all()])

      

Unfortunately, your approach is wrong. Even with your "work" approach, field selection is determined when the form is defined, not when it is created, so if you add items to the Model table, they will not appear in the select list.



You can avoid this by performing selection in __init__

your Form's method .

However, there is a much simpler approach. Instead of dynamically using the field selection functions, you should use a field specifically designed to select options from the model - ModelChoiceField

. This not only gets the list of model items dynamically when instantiated, but already includes an empty selection by default. See the documentation .

+8


source


Since this question and its answer almost solved the problem, I just wanted to add something. For me, the ID had to be empty, because the model did not recognize "0" as a valid parameter, but it did accept empty (null = True, blank = True). In the initializer:



self.fields['option_field'].choices = [
    ('', '------')] + [[r.id, r.name] for r in Model.objects.all()] 

      

0


source







All Articles