Django Inlineformsets - 使用 django-extra-views 进行自定义验证

Django Inlineformsets - Custom validation with django-extra-views

所以我有一个关于 django-extra-views 的 form_valid 的问题。我使用 CreateWithInlinesView 方法创建了一个具有多个内联表单集的表单。

称为“订单”的基本表单包含两个不同的表单集,“预订”和“付款”。一个订单必须至少包含一个预订,但在创建订单时不一定需要付款。

尽管如此,仍会生成付款表格。我想在“payment_amount”> 0 上验证付款表单。如果在创建订单时没有付款,则不应保存 PaymentInline。

views.py

class BookingInline(InlineFormSetFactory):
    model = Booking
    form_class = BookingForm
    prefix = 'booking_formset'
    factory_kwargs = {
        'extra': 0,
        'min_num': 1,
        'validate_min': True,
        'can_delete': True
    }

class PaymentInline(InlineFormSetFactory):
    model = Payment
    form_class = PaymentForm
    prefix = 'payment_formset'
    factory_kwargs = {
        'extra': 1,
        'min_num': 0,
        'validate_min': False,
        'can_delete': True
    }

class OrderCreateView(NamedFormsetsMixin, CreateWithInlinesView):
    model = Order
    inlines = [BookingInline, PaymentInline]
    inlines_names = ['booking_formset', 'payment_formset']
    form_class = OrderForm
    template_name = 'orders/order_form.html'

    def get_success_url(self):
        return reverse_lazy('order_detail', kwargs={'pk': self.object.pk})

    def forms_valid(self, form, inlines):
        """
        If the form and formsets are valid, save the associated models.
        """
        self.object = form.save(commit=False)
        self.object.created_by = self.request.user
        form.save(commit=True)
        for formset in inlines:
            formset.save()
        return HttpResponseRedirect(self.get_success_url())

所以逻辑需要像下面这样,虽然我得到一个错误说 'Order' 对象没有属性 'payment',因为它是一个反向关系...

views.py

def forms_valid(self, form, inlines):
    """
    If the form and formsets are valid, save the associated models.
    """
    self.object = form.save(commit=False)
    self.object.created_by = self.request.user
    form.save(commit=True)
    for booking_formset in inlines:
        booking_formset.save()
    for payment_formset in inlines:
        if self.object.payment.amount > 0:
            payment_formset.save()
        else:
            pass
    return HttpResponseRedirect(self.get_success_url())

有谁知道如何处理表单中的不同表单集?

提前致谢!

我不确定您的表单集上有哪些字段可用,但您可以使用 commit=False 保存,然后遍历未提交的付款实例以获得总付款金额。

def forms_valid(self, form, inlines):
    booking_formset = inlines[0]
    payment_formset = inlines[1]

    self.object = form.save(commit=False)
    self.object.created_by = self.request.user
    form.save(commit=True)
    booking_formset.save()

    payments = payment_formset.save(commit=False)
    total_payment = sum(payment.amount for payment in payments)
    if total_payment > 0:
        payment_formset.save()

    return HttpResponseRedirect(self.get_success_url())

更新:

booking_formset in inlines:payment_formset in inlines:会导致问题。假设 inlines 是一个列表,您将对该列表进行两次迭代。这相当于做下面的事情:

lst = [1, 2]
for x in lst:
    print(x)

for y in lst:
    print(y)

>>> 1
>>> 2
>>> 1
>>> 2