読者です 読者をやめる 読者になる 読者になる

Djangoroidの奮闘記

python,django,angularJS1~三十路過ぎたプログラマーの奮闘記

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が出てしまっていた。