首页 > 解决方案 > --View 处的 ValueError 未返回 HttpResponse 对象。它返回 None 而不是

问题描述

提交表单时出现此错误。

/en/checkout/ 处的 ValueError 视图 core.views.EnCheckoutView 未返回 HttpResponse 对象。它返回 None 代替。

这是它的views.py

class EnCheckoutView(View):
    def get(self, *args, **kwargs):
        try:
            order = Order.objects.get(user=self.request.user, ordered=False)
            form = CheckoutForm()
            context = {
                'form': form,
                'couponform': CouponForm(),
                'order': order,
                'DISPLAY_COUPON_FORM': True
            }
            shipping_address_qs = Address.objects.filter(user=self.request.user, address_type='S', default=True)
            if shipping_address_qs.exists():
                context.update({
                    'default_shipping_address': shipping_address_qs[0]
                })

            billing_address_qs = Address.objects.filter(user=self.request.user, address_type='B', default=True)
            if billing_address_qs.exists():
                context.update({
                    'default_billing_address': billing_address_qs[0]
                })

            return render(self.request, 'en-checkout-page.html', context)
        except ObjectDoesNotExist:
            messages.info(self.request, 'You do not have an active order.')
            return redirect('core:en-checkout')

    def post(self, *args, **kwargs):
        form = CheckoutForm(self.request.POST or None)
        try:
            order = Order.objects.get(user=self.request.user, ordered=False)
            if form.is_valid():
                use_default_shipping = form.cleaned_data.get("use_default_shipping")
                if use_default_shipping:
                    print('Using the default shipping address')
                    address_qs = Address.objects.filter(user=self.request.user, address_type='S', customer_name=customer_name, phone=phone, email=email, default=True)
                    if address_qs.exists():
                        shipping_address = address_qs[0]
                        order.shipping_address = shipping_address
                        order.save()
                    else:
                        messages.info(self.request, 'No default shipping address available')
                        return redirect('core:en-checkout')
                else:
                    print('User is entering a new shipping address')
                    customer_name = form.cleaned_data.get('customer_name')
                    phone = form.cleaned_data.get('phone')
                    email = form.cleaned_data.get('email')
                    shipping_address1 = form.cleaned_data.get('shipping_address')
                    shipping_address2 = form.cleaned_data.get('shipping_address2')
                    shipping_country = form.cleaned_data.get('shipping_country')
                    shipping_zip = form.cleaned_data.get("shipping_zip")
                    if is_valid_form([shipping_address1, shipping_country, shipping_zip]):
                        shipping_address = Address(
                            user=self.request.user,
                            customer_name=customer_name,
                            phone=phone,
                            email=email,
                            street_address=shipping_address1,
                            apartment_address=shipping_address2,
                            country=shipping_country,
                            zip=shipping_zip,
                            address_type='S'
                        )
                        shipping_address.save()
                        order.shipping_address = shipping_address
                        order.save()

                        set_default_shipping = form.cleaned_data.get('set_default_shipping')
                        if set_default_shipping:
                            shipping_address.default = True
                            shipping_address.save()

                    else:
                        messages.info(self.request, 'Please fill in the required shipping address fields')

                use_default_billing = form.cleaned_data.get('use_default_billing')
                same_billing_address = form.cleaned_data.get('same_billing_address')
                if same_billing_address:
                    billing_address = shipping_address
                    billing_address.pk = None
                    billing_address.save()
                    billing_address.address_type = 'B'
                    billing_address.save()
                    order.billing_address = billing_address
                    order.save()
                elif use_default_billing:
                    print('Using the default billing address')
                    address_qs = Address.objects.filter(
                        user=self.request.user,
                        address_type='B',
                        default=True
                    )
                    if address_qs.exists():
                        billing_address = address_qs[0]
                        order.billing_address = billing_address
                        order.save()
                    else:
                        messages.info(self.request, 'No default billing address')
                        return redirect('core:checkout')
                else:
                    print('User is entering a new billing address')
                    billing_address1 = form.cleaned_data.get('billing_address')
                    billing_address2 = form.cleaned_data.get('billing_address2')
                    billing_country = form.cleaned_data.get('billing_country')
                    billing_zip = form.cleaned_data.get('billing_zip')

                    if is_valid_form([billing_address1, billing_country, billing_zip]):
                        billing_address = Address(
                            user=self.request.user,
                            street_address=billing_address1,
                            apartment_address=billing_address2,
                            country=billing_country,
                            zip=billing_zip,
                            address_type='B'
                        )

                        billing_address.save()
                        order.billing_address = billing_address
                        order.save()
                        set_default_billing = form.cleaned_data.get('set_default_billing')
                        if set_default_billing:
                            billing_address.default = True
                            billing_address.save()
                    else:
                        messages.info(self.request, 'Please fill in the required billing address fields')

                payment_option = form.cleaned_data.get('payment_option')

                if payment_option == 'S':
                    return redirect('core:payment', payment_option='stripe')
                elif payment_option == 'P':
                    return redirect('core:payment', payment_option='paypal')
                else:
                    messages.warning(self.request, 'Invalid payment option selected')
                    return redirect('core:checkout')

        except ObjectDoesNotExist:
            messages.warning(self.request, 'You do not have an active order')
            return redirect('core:en-order-summary')

我很感激任何帮助!

标签: djangodjango-views

解决方案


您的方法中有太多代码post()- 您应该将所有逻辑提取到表单的保存方法中,使用适当的表单验证(尽可能使用模型表单),并将其拆分为简单、可读和可测试的方法。

话虽这么说,只要您提取下所有代码,您的问题就很明显了if form.is_valid()- 没有else分支。因此,如果您的表单未通过验证,则该函数确实会返回None

编辑

我将在 except.... 之前添加 else ,对吗?

你必须将它添加到与if form.is_valid()- 现在它最终出现在这盘意大利面中的位置,这超出了我的阅读能力,老实说:-/

作为一般规则,请考虑如果函数中有超过 20 行和 2 级缩进,那么可能是时候重构代码了。第一个明显的重构是移动事物以减少缩进级别。在您的情况下,您已经可以通过将except子句移动到唯一有意义的位置之后开始:

def post(self, *args, **kwargs):
    try:
        order = Order.objects.get(user=self.request.user, ordered=False)
    except Order.DoesNotExist:
        messages.warning(self.request, 'You do not have an active order')
        return redirect('core:en-order-summary')

    form = CheckoutForm(self.request.POST or None)
    if form.is_valid():
        # etc....

您已经获得了一级缩进(并将您的 try 块减少到严格的最小值,因此如果它出现在您正在调用的某些代码中,它将无法捕获另一个意外的 DoesNotExist 异常)。

然后正确使用表单验证 - 例如:

if address_qs.exists():
    shipping_address = address_qs[0]
    order.shipping_address = shipping_address
    order.save()
else:
    messages.info(self.request, 'No default shipping address available')
    return redirect('core:en-checkout')

这对您的用户来说是完全错误的并且非常粗鲁,他们将不得不再次重新输入所有内容。表单本身应该验证这一点。事实上,如果用户还没有默认送货地址,它甚至不应该显示“使用默认送货”选项。

实际上,您的视图代码应该看起来像:

def post(self, *args, **kwargs):
    try:
        order = Order.objects.get(user=self.request.user, ordered=False)
    except Order.DoesNotExist:
        messages.warning(self.request, 'You do not have an active order')
        return redirect('core:en-order-summary')


    form = CheckoutForm(self.request.POST, order=order)
    if form.is_valid():
        form.save() 
        # this  is supposed to has been validated by the form too
        payment_option = form.get_payment_option()
        return redirect('core:payment', payment_option=payment_option)

    # factor out all the common code creating the context
    # for both get and post in a get_context_data method
    context = self.get_context_data()
    context["form"] = form
    return render(self.request, 'en-checkout-page.html', context)

其他一切都应该在您的表单的验证和save()方法中。


推荐阅读