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.