【问题标题】:Django Inlineformsets - Custom validation with django-extra-viewsDjango Inlineformsets - 使用 django-extra-views 进行自定义验证
【发布时间】:2019-07-29 10:21:36
【问题描述】:

所以我有一个关于 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())

因此,逻辑需要类似于以下内容,尽管我收到一条错误消息,指出“订单”对象没有“付款”属性,因为它是反向关系...

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())

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

提前致谢!

【问题讨论】:

    标签: django forms validation inline-formset


    【解决方案1】:

    我不确定您的表单集中哪些字段可用,但您可以使用 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
    

    【讨论】:

    • 感谢您的快速回复,我确实使用了 payment.amount 字段。我确实遇到了一个奇怪的错误; “预订”对象没有“金额”属性。看起来它试图验证两个表单集,而不仅仅是 payment_formset...
    • 非常感谢!不过最后一个问题,您对 booking_formset = inlines[0] 做了什么?我确实得到了问题是尝试对所有表单集进行两次迭代。
    • 你保存它。我不使用这个包,但我猜inlines 是一个表单集类的列表。 inlines[0] 返回您的 BookingInline 以及来自您的 POST 请求的经过验证的数据。您所做的只是将类分配给一个变量,以便您可以保存它,或者在您的付款表单集的情况下,做一些进一步的验证。
    猜你喜欢
    • 1970-01-01
    • 2016-07-05
    • 1970-01-01
    • 2014-05-31
    • 2021-09-26
    • 2012-05-06
    • 1970-01-01
    • 2012-05-23
    相关资源
    最近更新 更多