dstav blog

TIL: How to pass data-arguments from objects to ChoiceWidget-based widget

  • Published on
  • Edited on

If you are using Django's ModelChoiceField or ModelMultipleChoiceField in a form, you likely use a ChoiceWidget-based widget to display the options in the template. These widgets, such as a radio button or checkbox, display the string representation of the object in the queryset provided when the field is defined. In some cases, you may need to pass more information related to the object, e.g. the price of an item, to process it on the client side.

You can use data- attributes which is a standard way to extend HTML elements by providing more information. To achieve this, you need to override the create_option method of the corresponding ChoiceWidget-based widget you use. In the example below, I used forms.widgets.CheckboxSelectMultiple. After calling super() to let Django do its normal processing, you should update the option_attrs dictionary with the attribute you want (prepend the name with data- to follow the standard). The object is accessible though value.instance.

For example, let's say you have a form that allows users to select items from a list of products and add them to a shopping cart. Using the following custom widget, you can display the name of each product as the label for the checkbox or radio button, but also pass the price of each product as a data attribute. This allows you to easily access the price of each selected product on the client side and calculate the total cost of the shopping cart before submitting the form.

class YourCustomWidget(forms.widgets.CheckboxSelectMultiple):
    def create_option(
        self, name, value, label, selected, index, subindex=None, attrs=None
    ):
        option_attrs = super().create_option(
            name, value, label, selected, index, subindex, attrs
        )
        option_attrs["attrs"].update({"data-price": value.instance.price})
        return option_attrs