Django:创建类似于django admin的内联表单

时间:2014-08-15 04:53:12

标签: django django-forms

以前曾经问过,但没有回答(从我能找到的内容)。

我有两个型号;

class Invoice(models.Model):
    invoice_number = models.CharField(max_length=30)
    invoice_date = models.DateField()

class LineItem(models.Model):
    description = models.CharField(max_length=50)
    unit_price = models.DecimalField(max_digits=9, decimal_places=2)
    quantity = models.PositiveSmallIntegerField()
    invoice = models.ForeignKey(Invoice)

在django管理界面中,我将LineItem作为内联发票。这很有效,因为我想在提高发票的同时添加发票行项目。

是否有关于在django应用程序中实现类似嵌套/内联表单的示例模式?我想向用户呈现的视图类似于管理界面,其中可以在创建发票时输入lineitems。

感谢任何指导。

2 个答案:

答案 0 :(得分:1)

我已经研究了我在这里收到的一些建议,并且已经决定了一个稍微不同的解决方案,但是@rix建议使用django formsets非常正常;基于模型的inlineformset。

我最终使用django inlineformset_factory作为LineItems并将Invoice保留为标准ModelForm

我的表格;

#forms.py
...
class LineItemForm(ModelForm):
    class Meta:
        model   = LineItem
        fields  = ['description','unit_price','quantity']

class InvoiceForm(ModelForm):
    class Meta:
        model   = Invoice
        fields  = ['invoice_date','invoice_number']

我的观点;

#views.py
...
def add_invoice(request):
    LineItemFormSet = inlineformset_factory(Invoice, LineItem, form=LineItemForm, extra=5)
    if request.method == 'POST':
        invoice_form = InvoiceForm(request.POST, prefix='invoice')
        lineitem_formset = LineItemFormSet(request.POST, request.FILES, prefix='line')
        if invoice_form.is_valid() and lineitem_formset.is_valid():
            invoice = invoice_form.save()
            # I recreate my lineitem_formset bound to the new invoice instance
            lineitem_formset = LineItemFormSet(request.POST, request.FILES, prefix='line', instance=invoice)
            # I have to validate (again - so I'm confident) to access clean data
            lineitem_formset.is_valid()
            lineitem_formset.save()
            if 'submit_more' in request.POST:
                return HttpResponseRedirect(reverse('invoices:add_invoice'))
            else:
                return HttpResponseRedirect(reverse('invoices:get_invoices'))
        else:
            return render(request, 'invoices/invoice_add.html', {
                'message'           : "Check your form",
                'invoice_form'      : invoice_form,
                'lineitem_formset'  : lineitem_formset,
            })
    else:
        invoice_form = InvoiceForm(prefix='invoice')
        lineitem_formset = LineItemFormSet(prefix='line')
        return render(request, 'invoices/invoice_add.html', {
            'invoice_form'      : invoice_form,
            'lineitem_formset'  : lineitem_formset,
        })

现在,正如@ tr33hous所建议的,我正在玩JS以添加新的内联表单。

我对结果非常满意。

但是,我想知道是否有更好的方法然后创建和验证我的内联formset以确保它在保存我的发票之前全部有效,然后重新创建绑定到新发票实例的formset对象,而不是主要的开销,但它看起来并不干净。

答案 1 :(得分:0)