Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 269
HenryM Avatar asked Oct 18 '25 06:10

HenryM


2 Answers

In case of MultiWidget, similarly to @HenryM's answer, one can subclass get_context method and assign values like so:

def get_context(self, name, value, attrs):
    context = super().get_context(name, value, attrs)
    context["some_field"] = "some_value"
    return context

Which in template can be accessed by {{ some_field }}

like image 75
BaconBad Avatar answered Oct 20 '25 19:10

BaconBad


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.

like image 20
HenryM Avatar answered Oct 20 '25 20:10

HenryM