Home > Software design >  How to change the default labels of a ForeignKey field whose form's widget is a RadioSelect
How to change the default labels of a ForeignKey field whose form's widget is a RadioSelect

Time:10-03

In my Django app, I have this form:

from django import forms
from main.models import Profile

class ProfileForm(forms.ModelForm):

    class Meta:
        model = Profile
        fields = ['picture']

        widgets = {
            'picture': forms.RadioSelect(),
        }

By default, the labels of the picture field within the template are generated according to the __str__() method of the Picture model. That's because the picture field on my Profile model is actually a ForeignKey field to a Picture model.

However, the value returned by that __str__() method doesn't make much sense in this particular template, and changing it is not possible because it's being used elsewhere.

Therefore, is there a way I might change the default labels for the picture field of my ProfileForm? For instance, changing from the __str__()'s default picture.src ' (' picture.description ')' to something like picture.description only?

I have checked what the docs had to say regarding the label_from_instance, but I didn't understand how to apply it. In fact, I couldn't even understand if that would be a solution for this case.

Some similiar questions here on Stack Overflow also mentioned that link of the docs, but the questions's forms were slightly different than mine, and I ended up not understanding them either.

CodePudding user response:

If you want to use label_from_instance, you should make a specific widget with:

class PictureField(forms.ModelChoiceField):
    def label_from_instance(self, obj):
        return obj.description


class ProfileForm(forms.ModelForm):
    picture = PictureField(Picture.objects)

    class Meta:
        model = Profile

On another hand, you can use your code and in init function of your form to change the choices attribute of the picture field

CodePudding user response:

It turns out I didn't need to use label_from_instance. I just needed to create a subclass of django.forms.RadioSelect and override its create_option() method, setting the label by giving option['label'] the value I'd like, just like this:

from django import forms
from main.models import Profile

class PictureRadioSelect(forms.RadioSelect):
    def create_option(self, name, value, label, selected, index, subindex=None, attrs=None):
        option = super().create_option(name, value, label, selected, index, subindex, attrs)
        option['label'] = value.instance.description
        return option

class ProfileForm(forms.ModelForm):

    class Meta:
        model = Profile
        fields = ['picture']

        widgets = {
            'picture': PictureRadioSelect(),
        }

This section of the docs explains this in greater detail. It actually describes how to override django.forms.Select options, but I tested it with django.forms.RadioSelect and it ran as expected.

  • Related