pythondjangodjango-templatescustomizationdjango-widget

Override the template of a widget and pass values to it with Django 4.0


I am creating a simple app to do product reviews. I have a Product, Manufacturer and Review models which I will now summarize

class Manufacturer(models.Model):
    name = models.CharField()

class Product(models.Model):
    name = models.CharField()
    manufacturere = models.ForeignKey(Manufacturer)

class Review(models.Model):
    title = CharField()
    product = models.ForeignKey(Product)

I created a ModelForm to create the review. So far I was only able to create a custom widget with an overridden template.

class CustomSelectWidget(forms.widgets.Select):
    option_template_name = 'widgets/select_option.html'

class NewReviewForm(forms.ModelForm):
    review = forms.ModelMultipleChoiceField(
        queryset = Review.objects.none(),
        widget = CustomSelectWidget(),
    )
    class Meta:
        model = Review
        fields = '__all__'

The form view is a normal function based view. The review field is rendered with a list of products in a <select>.What I want to do is change the text inside <option> to make it so that the manufacturer's name is also there. IMPORTANT: I have to take the manufacturer's name from the respective Object, I can't just insert it into the Product name field. ES:

what I have now

the goal


Solution

  • You can override create_option in the widget:

    class CustomSelectWidget(forms.widgets.Select):
        option_template_name = 'widgets/select_option.html'
    
        def create_option(self, name, value, label, selected, index, subindex=None, attrs=None):
            label = f"{value.instance.product.name} {value.instance.title}"
            return super().create_option(name, value, label, selected, index, subindex, attrs)