Search code examples
pythondjangoforms

Django: Select a valid choice. [..] is not one of the available choices using TextChoices


Here's my error upon the process of validation of a form.

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

Here's the different pieces of code I have.
models.py:

class Cat(models.Model):
    class Sex(models.TextChoices):
        M = 1, 'Male'
        F = 2, 'Female'
     
     sex = models.PositiveSmallIntegerField(choices=Sex.choices, blank=False, null=False)

forms.py:

class CatForm(forms.ModelForm):
    # Other fields that I think are useless in this error but maybe I'm missing something for the TextChoice of sex to work out here?
    fur_color = forms.ModelMultipleChoiceField(queryset=FurColor.objects.get_all(), required=False, widget=forms.CheckboxSelectMultiple)
    birth_date = forms.DateField(widget = forms.SelectDateWidget(years=range(1980, 2023)))
    class Meta:
        model = Cat
        exclude = ('user','registered_on')

views.py

def register_cat(request):
    context = {}
    print(request.method)
    if request.method == 'POST':
        context['form'] = CatForm(data=request.POST)
        if context['form'].is_valid():
            cat = context['form'].save(commit=false)
            cat.user = request.user
            cat.save()
            return redirect('meet')
    else:
        context['form'] = CatForm()
    return render(request, 'register_cat.html', context)

The sex field in the form appear as a select list, but when I select either of Male or Female, it doesn't seems to be able to make the link back in the model.

Do I need do modify my forms.py to make it work. Or is my model flawed to begin with ? I have Django 4.2.5.


Solution

  • This is likely because you use TextChoices subclass, you probably should use an IntegerChoices object:

    class Cat(models.Model):
        class Sex(models.IntegerChoices):
            M = 1, 'Male'
            F = 2, 'Female'
    
        sex = models.PositiveSmallIntegerField(
            choices=Sex.choices, blank=False, null=False
        )

    The choices will have as difference that the choices for a TextChoices are '1' and '2', so strings, whereas for IntegerChoices, these are 1 and 2, so integers.