Search code examples
djangodjango-formsdjango-widget

How to add additional context to a django form widget


the basic Django CheckboxSelectMultiple widget allows for a label and value to be passed through to the template. I want to add 2 additional fields from a model but I cannot work out how, although I believe it is through subclassing get_context

I have this model and I would like to include the icon and description in the widget

class AddOnItem(models.Model):
    name = models.CharField(
        verbose_name = 'AddOn Title',
        max_length = 50
    )
    description = models.CharField(
        verbose_name = 'Description',
        max_length = 255
    )
    icon = models.FileField(upload_to="addon_icons/", blank=True, null=True)
    active = models.BooleanField(default=False)

Within my form I've specified this widget

class JobPostWizardForm1(forms.ModelForm):
    class Meta:
        model = Job
        fields = [
            ...,
            'addons'
            ]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        ...

        self.fields['addons'].widget = AddOnCheckboxSelectMultiple()
        self.fields['addons'].queryset = AddOnItem.objects.filter(active=True)

And I've subclassed the CheckboxSelectMultiple widget as

class AddOnCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
    template_name = 'jobboard/widgets/addon_checkbox_select.html'
    option_template_name = 'jobboard/widgets/addon_checkbox_option.html'

    def get_context(self, name, value, attrs):
        context = super().get_context(name, value,attrs)
        return context

Obviously this doesn't do anything at the moment but I want to add something like

context['icon'] = obj.icon

but I cannot work out how to do this. That is, I do not follow how Django widgets are getting the object.

I would greatly appreciate any help available - thanks


Solution

  • This might not be the best solution, but it works.

    I override create_option like so:

    def create_option(self, name, value, label, selected, index, subindex=None, attrs=None):
        ctx = super().create_option(name, value, label, selected, index, subindex=subindex, attrs=attrs)
        obj = AddOnItem.objects.get(id=int(value))
        ctx['icon'] = obj.icon
        ctx['description'] = obj.description
        ctx['price'] = obj.price
    
        return ctx
    

    I can then get these attributes with {{ widget.field_name }} within the template.