Django - How to iterate and inspect each choice for a ModelChoiceField in the template code
I have a form (edited for brevity) as follows:
class InteractionForm(forms.Form):
def __init__(self, *args, **kwargs):
# Each object within this queryset is a model object of type InteractionChoice
choices_qs = interaction.interactionchoice_set.all()
self.fields['choices'] = forms.ModelChoiceField(
widget=forms.RadioSelect(),
queryset=choices_qs,
The InteractionChoice
model looks like:
class InteractionChoice(models.Model):
interaction = models.ForeignKey(Interaction)
name = models.CharField(max_length=255)
is_answer = models.BooleanField(default=False)
An instance of InteractionForm
is passed from a view to a template and rendered via:
{{ form.choices }}
My question is whether there is a way to iterate over each choice in my template and access one of its properties -- specifically, the is_answer
property defined in InteractionChoice
. The purpose being to customize how a choice is displayed if it is indeed the answer. More specifically, if is_answer
is True, I'd possibly change the class
attribute on the <label>
for that choice.
Perhaps, I'm approaching this problem from the wrong direction. If anyone has pointe开发者_运维知识库rs for alternative ideas, I'd be happy to hear them.
Thanks in advance.
Update 1:
Thinking about this more after @rczajka's response, I don't believe I can achieve what I'm hoping to do in the template code. Instead, if the purpose is to modify the tag's class attribute, I should perhaps be looking to subclass and override certain methods in forms.widgets.RadioInput
, forms.widgets.RadioFieldRenderer
, and forms.widgets.RadioSelect
. I'll dig into this more.
I came up with one solution that addresses this problem. It's hackish, to say the least, but it's the only approach I've thought of that works thus far without a lot of back-end changes to my existing design.
My approach stemmed from this article on subclassing `RadioFieldRenderer' and 'RadioSelect'.
In the __unicode__
method for an InteractionChoice
model, I return:
return self.name + "_" + str(self.is_answer)
which is the value used for a radio button's label (amongst other things). I then subclassed forms.widgets.RadioInput
, forms.widgets.RadioFieldRenderer
, and forms.widgets.RadioSelect
.
For the custom RadioInput class, I overrode its __unicode__
method to include logic to append a class
string – whose value is ultimately dictated by the string returned from the unicode method in InteractionChoice
– to the <label>
tag string it returns.
For the custom RadioFieldRenderer class, I overrode __iter__
and __getitem__
to use the custom RadioInput class.
For the custom RadioSelect class, I overrode the renderer
property to use my custom radio field renderer.
This is obviously far from an ideal solution. Hopefully, a better one will arise.
I found a similar problem but solved it in a different way.
How to get ModelChoiceField instances in the template
Iterating over the field's queryset property.
You should subclass ModelChoiceField and override label_from_instance. It says so here: https://docs.djangoproject.com/en/dev/ref/forms/fields/#modelchoicefield:
The unicode method of the model will be called to generate string representations of the objects for use in the field's choices; to provide customized representations, subclass ModelChoiceField and override label_from_instance. This method will receive a model object, and should return a string suitable for representing it.
精彩评论