Django e-commerce part56 Checkout Form & Form mixin
チェックアウトフォームと、フォームのmixinを作成する
order/forms.py を作成
from django import forms class GuestCheckoutForm(forms.Form): email = forms.EmailField() email2 = forms.EmailField(label='確認用') def clean_email(self): email = self.cleaned_data.get("email") email2 = self.cleaned_data.get("email2") if email == email2: return email2 else: raise form.ValidationError("入力されたメールアドレスを再度ご確認お願いします。")
carts/views.py のCheckoutViewにformをimportする。
from django.views.generic.edit import FormMixin ... from orders.forms import GuestCheckoutForm ::: class CheckoutView(FormMixin, DetailView): model = Cart template_name = "carts/checkout_view.html" form_class = GuestCheckoutForm def get_object(self, *args, **kwargs): cart_id = self.request.session.get("cart_id") if cart_id == None: return redirect("cart") cart = Cart.objects.get(id=cart_id) return cart def get_context_data(self, *args, **kwargs): context = super(CheckoutView,self).get_context_data(*args, **kwargs) user_can_continue = False if not self.request.user.is_authenticated():# or if request.user.is_guest: context["login_form"] = AuthenticationForm() context["next_url"] = self.request.build_absolute_uri() if self.request.user.is_authenticated(): user_can_continue = True context["user_can_continue"] = user_can_continue context["form"] = self.get_form() return context
ポイント
- FormMixin importする。
Editing mixins | Django documentation | Django
FormMixin の変数の1つの、form_class に、GuestCheckoutFormに代入する。(このformを代入して、そのフォームをinstance化する。)
FormMixin のメソッド get_form() で、contextとして、formを渡す。(ちなみに、get_form_class()というメソッドもあり、そちらは、form_classが与えられていない時に、form classを引数にすると、formをinstance化して渡せる。form_classと、get_form()の合わせ技のようなもの。get_form_class(GuestCheckoutForm)で、今回と同じものになる。)
checkout_view.html を編集
ゲストユーザー用のemail登録フォームを作ってみる。
<div class='col-sm-6'> <p class="lead">ゲストユーザーとして買い物を続ける</p> <form method='POST' action=''>{% csrf_token %} {{ form|crispy }}<!-- ここはcontextから引き継いだform --> <input type='submit' class='btn btn-success' value='ゲストユーザーとして買い物を続ける' /> </form> </div>
orders/views.py にpost, get_success_urlなどを上書きする。
class CheckoutView(FormMixin, DetailView): model = Cart template_name = "carts/checkout_view.html" form_class = GuestCheckoutForm ... def post(self, request, *args, **kwargs): form = self.get_form() if form.is_valid(): # print (form.cleaned_data.get("email")) return self.form_valid(form) else: return self.form_invalid(form) def get_success_url(self): return reverse("checkout") ...
- form_valid, invalidは、FormMixinのメソッド。form_valid -> get_success_urlに飛ぶ。form_invalidは、(Renders a response, providing the invalid form as context. invalid formをcontextとして、渡す)Editing mixins | Django documentation | Django
ここでちょっとハマったところ。
from django import forms class GuestCheckoutForm(forms.Form): email = forms.EmailField() email2 = forms.EmailField(label='email(確認用)') def clean_email2(self):#ここをclean_email(self)にしてしまっていた。 email = self.cleaned_data.get("email") email2 = self.cleaned_data.get("email2") if email == email2: return email2 else: raise forms.ValidationError("入力されたメールアドレスを再度ご確認お願いします。")
clean_email2をclean_emailにしていたために、email の方のチェックをしてしまっていた。そのため、email=email2を返すようになっており、valid errorが出てしまっていた。