BoldMarshmallow BoldMarshmallow - 8 days ago 5
Python Question

How to edit select option values in Django forms?

I want to edit select option values in my django form.
Right now the value for option in select is the related variant_id.

models.py

class ReceiptDetail(models.Model):
variant = models.ForeignKey('ProductVariant')


forms.py

class ReceiptDetailForm(forms.ModelForm)
class Meta:
model = ReceiptDetail
fields = ['product_id', 'variant', 'size', 'quantity', 'price']


the resulting html from select on 'variant':

<option value="" selected="selected">---------</option>
<option value="98">Charm I (Charm I)</option>
<option value="97">Small potion V (Small potion V)</option>
<option value="90">Big potion V (Big potion V)</option>
<option value="100">Charm III (Charm III)</option>
<option value="93">Small potion I (Small potion I)</option>
<option value="94">Small potion II (Small potion II)</option>
<option value="81">Colorfully (Colorfully)</option>


Note that the value for each option is the VARIANT id. I want to change that value to PRODUCT id (that's related to the variant).

I'm guessing widgets are the answer, but I don't know how to access the option attributes inside the select object. Here's what I've tried:

widgets.py:

class VariantIDWidget(forms.widgets.Select):

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

def render(self, name, value, attrs=None):
out = super(VariantIDWidget, self).render(name, value,
attrs={'value': 'test'})
return out


This will change the value of <\select>, not its related <\options>.

Answer

I think you should exclude the variant in the fields defined in your form, and do something in the form __init__ method:

class ReceiptDetailForm(forms.ModelForm)    
    class Meta:
        model = ReceiptDetail
        fields = ['product_id', 'size', 'quantity', 'price']

    def __init__(self, *args, **kwargs):
        super(ReceiptDetailForm, self).__init__(*args, **kwargs)
        # this is pseudo code but you should get all variants
        # then get the product related to each variant
        variants = Variant.objects.all()
        products = [(i.product.id, i.product.name) for i in variants]
        self.fields['product'] = forms.ChoiceField(choices=products)

It's a common technique, see some other SO questions.