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

Question:

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

  • Geforce RTX2080
  • MAXSUN AMD Radeon RX 550
  • Arca770

the goal

  • NVIDIA – Geforce RTX2080
  • AMD – MAXSUN Radeon RX 550
  • INTEL – Arca770
Asked By: Tiziano Pedrazzoli

||

Answers:

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)

Answered By: Lucas Grugru