user1102171
user1102171

Reputation: 684

django forms give: Select a valid choice. That choice is not one of the available choices

I am unable to catch the values from the unit_id after the selection is done by the user and data is posted. Can someone help me to solve this.

The values of the unit_id drop down list is obtained from another database table (LiveDataFeed). And once a value is selected and form posted, it gives the error:

Select a valid choice. That choice is not one of the available choices.

Here is the implementation:

in models.py:

class CommandData(models.Model):
    unit_id = models.CharField(max_length=50)
    command = models.CharField(max_length=50)
    communication_via = models.CharField(max_length=50)
    datetime = models.DateTimeField()
    status = models.CharField(max_length=50, choices=COMMAND_STATUS)  

In views.py:

class CommandSubmitForm(ModelForm):
    iquery = LiveDataFeed.objects.values_list('unit_id', flat=True).distinct()
    unit_id = forms.ModelChoiceField(queryset=iquery, empty_label='None',
        required=False, widget=forms.Select())

class Meta:
    model = CommandData
    fields = ('unit_id', 'command', 'communication_via')

def CommandSubmit(request):
    if request.method == 'POST':
        form = CommandSubmitForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponsRedirect('/')
    else:
        form = CommandSubmitForm()

    return render_to_response('command_send.html', {'form': form},
        context_instance=RequestContext(request))

Upvotes: 24

Views: 51164

Answers (5)

Jerim Kaura
Jerim Kaura

Reputation: 1

What worked for me is populating the choices to the form before calling the is_valid() method.

form = CommandSubmitForm(request.POST)
form.fields["unit_id"].choices = choices
if form.is_valid():
  # add your logic here

Upvotes: 0

Петр Сачек
Петр Сачек

Reputation: 29

Rewrite the _init function. Use Limited_condition variable that delete this field in update view. in my case 'author' field caused problem 'Select a valid choice'. I just removed it in initiation of the form.

forms.py
    class UrlentryForm(ModelForm):
class Meta:
    model = Urlentry
    fields = ['url_text', 'author', 'url_id', 'datetime_available_from', 'datetime_available_to', 'partner_ads','qr_code','snapshot']
def __init__(self, *args, **kwargs):
    limited_condition = kwargs.pop('limited_condition', None)
    super(UrlentryForm, self).__init__(*args, **kwargs)
    if limited_condition:
        del self.fields['author']
        self.fields['url_id'].widget = HiddenInput()
        self.fields['url_id'].required = False
        self.fields['qr_code'].widget = HiddenInput()
        self.fields['qr_code'].required = False
        self.fields['snapshot'].widget = HiddenInput()
        self.fields['snapshot'].required = False

Then modify views.py

views.py
    @login_required(login_url=reverse_lazy('auth:login'))
    def update_urlentry(request, pk):
        #....
    if request.method == "POST":
            urlentry_form = UrlentryForm(request.POST, instance=urlentry, limited_condition=True)
            if urlentry_form.is_valid():
                urlentry = urlentry_form.save(commit=False)
                # additional modification of urlentry, if needed
                urlentry.save()
    else:
        messages.error(request, urlentry_form.errors)
    redirect('polls:detail', pk=urlentry.pk)

#and finalizing code follows here

Upvotes: 0

Oth  Bhns
Oth Bhns

Reputation: 1

this is an old question but i faced the same problem, the solution according the django docs is to add to_field_name="name" where name is the column you want to show on the choices

iquery = LiveDataFeed.objects.values_list('unit_id', flat=True).distinct()
unit_id = forms.ModelChoiceField(queryset=iquery, empty_label='None',
    required=False, widget=forms.Select(),to_field_name="unit_id")

Upvotes: 0

brave-hawk
brave-hawk

Reputation: 311

Before you call form.is_valid(), do the following:

  1. unit_id = request.POST.get('unit_id')

  2. form.fields['unit_id'].choices = [(unit_id, unit_id)]

Now you can call form.is_valid() and your form will validate correctly.

Upvotes: 8

Dan Breen
Dan Breen

Reputation: 12924

You're getting a flat value_list back which will just be a list of the ids, but when you do that, you're probably better off using a plain ChoiceField instead of a ModelChoiceField and providing it with a list of tuples, not just ids. For example:

class CommandSubmitForm(ModelForm):
    iquery = LiveDataFeed.objects.values_list('unit_id', flat=True).distinct()
    iquery_choices = [('', 'None')] + [(id, id) for id in iquery]
    unit_id = forms.ChoiceField(iquery_choices,
                                required=False, widget=forms.Select())

You could also leave it as a ModelChoiceField, and use LiveDataFeed.objects.all() as the queryset, but in order to display the id in the box as well as have it populate for the option values, you'd have to subclass ModelChoiceField to override the label_from_instance method. You can see an example in the docs here.

Upvotes: 19

Related Questions