开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜