Существует 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()
метода.