外键上的ModelChoiceField不起作用

时间:2019-05-15 16:43:03

标签: django django-forms

我在模型中有一个外键,我想自定义它在表单中的显示方式。默认情况下,会出现一个选择,其选项值为id。我想将选项值更改为另一个字段。

Models.py:

class PriceDetails(models.Model):
    id = models.AutoField(primary_key=True)
    size = models.ForeignKey(SizeOd, blank=True, null=True, on_delete=models.DO_NOTHING)

    def __str__(self):
        return str(self.id)
class SizeOd(models.Model):
    size = models.DecimalField(unique=True, decimal_places=1, max_digits=5)
    multiplier = models.DecimalField(unique=True, decimal_places=3, max_digits=8)

    def __str__(self):
        return str(self.size)

Forms.py:

class PriceDetailsForm(forms.ModelForm):
    size = forms.ModelChoiceField(queryset=SizeOd.objects.order_by('size'), to_field_name="multiplier", required=False)
    class Meta:
        model = PriceDetails
        exclude = ('id',)

Views.py:

class PriceDetailsInline(InlineFormSetFactory):
    model = models.PriceDetails
    form = forms.PriceDetailsForm
    fields = '__all__'
    factory_kwargs = {'extra': 1, 'can_delete': False}

class CreateInvoiceView(LoginRequiredMixin, CreateWithInlinesView):
    model = models.Invoice
    form = forms.InvoiceForm
    inlines = [PriceDetailsInline]
    fields = '__all__'
    template_name = 'app/invoice_form.html'

Template:invoice_form.html:

<form method="post">
    {% csrf_token %}
    {{form.as_p}}
    <div id="FormSet" class="my_inline">
        {% for formset in inlines %}
            <table id="FormSet{{ formset.prefix }}{{ forloop.counter }}">
                {{ formset.as_table }}
            </table>
            {{ formset.management_form }}

        {% endfor %}
    </div>
    <input type="submit" value="Create Invoice" >
</form>

<script type="text/javascript">
$(function() {
    {% for formset in inlines %}
        $('table#FormSet{{ formset.prefix }}{{ forloop.counter }}').formset();
    {% endfor %}
});
</script>

默认值:

<select>
<option value='id1'>size1</option>
<option value='id2'>size2</option>
</select>

预期:

<select>
<option value='*multiplier1*'>size1</option>
<option value='multiplier2'>size2</option>
</select>

编辑:My output 这里的选项值是id,我希望它们是倍数。 ModelChoiceField不会进行任何更改。如果我完全消除“ size = forms.ModelChoiceField(queryset = SizeOd.objects.order_by('size'),to_field_name =“ multiplier”,required = False)',则选择框(大小字段)将显示为相同。相反,它应该根据大小对选择框上的显示文本进行排序,并将乘数附加为值。

2 个答案:

答案 0 :(得分:0)

您可以通过更改返回字段来自定义表单的模型外观

class PriceDetails(models.Model):
    ...

    def __str__(self):
        return str(self.size) # <--change this here from .id --> .size

已编辑

答案 1 :(得分:0)

找到了解决方法here。 问题不在于ModelChoiceField。在forms.py中所做的任何更改均未反映在表单中。 (由于使用了InlineFormSetFactory) 在views.py中重写construct_inlines()(这是extra_views.advanced.ModelFormWithInlinesMixin的一部分)

class CreateInvoiceView(LoginRequiredMixin, CreateWithInlinesView):
model = models.Invoice
form = forms.InvoiceForm
inlines = [PriceDetailsInline]
fields = '__all__'
template_name = 'app/invoice_form.html'
def construct_inlines(self):
    inline_formsets = super(CreateInvoiceView, self).construct_inlines()
    inline_formsets[0].forms[0].fields['size'].queryset = models.SizeOd.objects.order_by('size')
    inline_formsets[0].forms[0].fields['size'].to_field_name = 'multiplier'
    return inline_formsets