djangodjango-forms

'to_field_name' argument on a ModelChoiceField() doesn't seem to be working


Well, pretty much what it says in the title.

I'm creating a ModelChoiceField() in one of my Forms, like so:

class FormCreatePlace(forms.ModelForm):
    (...)
    category = forms.ModelChoiceField(queryset=Category.objects.all(), to_field_name='name')
    (...)

The Category model is defined like so:

class Category(models.Model):
    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.CharField(max_length=40)

And yet the field itself on the HTML form insists on displaying the primary keys (a series of UUIDs) as the choices.

What am I doing wrong?


Solution

  • The to_field_name is used to change the value of the options, not the displayed text

    The easiest way to change the displayed text is to change the __str__ method on your model to return the name field:

    class Category(models.Model):
        uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
        name = models.CharField(max_length=40)
    
        def __str__(self):
            return self.name
    

    However, that will affect how the categories are displayed elsewhere. If you don't want to do that, you can subclass ModelChoiceField and override label_from_instance.

    class MyModelChoiceField(ModelChoiceField):
        def label_from_instance(self, obj):
            return obj.name
    

    Then use your choice field in the form.

    class FormCreatePlace(forms.ModelForm):
        (...)
        category = forms.MyModelChoiceField(queryset=Category.objects.all())
    

    See the ModelChoiceField docs for more info.