ValueError в --View не возвращает объект HttpResponse. Вместо этого он вернулся - PullRequest
0 голосов
/ 23 января 2020

Я получил эту ошибку при отправке формы.

ValueError at / en / checkout / Представление core.views.EnCheckoutView не возвращало объект HttpResponse. Вместо этого он вернул None.

  • Я дважды проверил views.py

  • Иногда после удаления файла базы данных (db.sqlite3 ): он работал правильно с тем же шаблоном views.py и html, но после перезагрузки компьютера снова появляется та же ошибка.

и вот его 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')

Я ценю любую помощь !!

1 Ответ

1 голос
/ 23 января 2020

Существует waaayyyyy слишком много кода в вашем методе post() - вы должны извлечь все логи c в метод сохранения формы, использовать правильную проверку формы (используйте как можно больше моделей) и разделите его на простые, удобочитаемые и тестируемые методы.

При этом ваша проблема становится очевидной, как только вы извлекаете весь код из if form.is_valid() - ветки else нет. Поэтому, если ваша форма не проверяется, функция действительно возвращает None.

РЕДАКТИРОВАТЬ

Я добавлю еще прямо перед тем, кроме ... ................, правильно?

Вы должны добавить его на том же уровне, что и 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....

Вы уже получили один уровень отступа (и сократили свой блок попытки до строгого минимум, поэтому он не сможет перехватить другое непредвиденное исключение 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() метода.

...