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

Djangoroidの奮闘記

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

Django e-commerce part57 Save Guest Info

ゲストユーザの情報をsaveする

carts/view.py 2、orders/models.py UserCheckoutをimportする。

post メソッドに、formでゲットしたemailと、UserCheckoutで、createしたuserを、user_checkoutとして、代入する。これで、usercheckoutに、インスタンスが保存される。

from orders.models import UserCheckout
...
    def post(self, request, *args, **kwargs):
        form = self.get_form()
        if form.is_valid():
            email = form.cleaned_data.get("email")
            user_checkout = UserCheckout.objects.create(email=email)
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

UserCheckoutのemailをuniqueにする。

    email = models.EmailField(unique=True)

orders/forms.py の修正

こちらでもメールアドレスがすでに登録されていないかを調べる。厳密は、メールアドレスで登録されているユーザーがいないかどうかを調べる。存在する場合は、エラーを出す。

from django import forms
from django.contrib.auth import get_user_model

User = get_user_model()


class GuestCheckoutForm(forms.Form):
    email = forms.EmailField()
    email2 = forms.EmailField(label='email(確認用)')

    def clean_email2(self):
        email = self.cleaned_data.get("email")
        email2 = self.cleaned_data.get("email2")

        if email == email2:
            user_exists = User.objects.filter(email=email)=count.()
            if user_exists != 0;
                raise forms.ValidationError("すでにこちらのメールは登録済みです。ログインしてください。")
            return email2
        else:
            raise forms.ValidationError("入力されたメールアドレスを再度ご確認お願いします。")

ポイント

  • get_user_model()で、auth.userのインスタンス一覧をゲットできる。それをUserに代入する。そうすることで、User.objects でユーザーの一覧がゲットできる。

carts/views.py のvalidationerrorの時の、attribute errorを解消する。

CheckoutView object has no attribute 'object' というエラーが出ると思うので、このようなエラーは、文字通りobjectを作ってあげれば、errorが解消する。

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        form = self.get_form()
        if form.is_valid():
            email = form.cleaned_data.get("email")
            user_checkout = UserCheckout.objects.create(email=email)
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

ポイント

  • 上記で、ユーザー登録がある人が、同じメアドでゲストユーザーとして買い物を続けようとすると、is_valid()がfalseになって、validationerrorが発生する。ただ、ゲストユーザーが同じメアドで、2回目の買い物をしようとした時に、validationerrorは発生せずに、models.pyのunique trueに関するerrorが出てしまう。そのため、user_checkout = UserCheckout.objects.get_or_create(email=email)で、ない場合とある場合でケースを分ける。
    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        form = self.get_form()
        if form.is_valid():
            email = form.cleaned_data.get("email")
            user_checkout = UserCheckout.objects.get_or_create(email=email)
            print(user_checkout)
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

上記で、print(user_checkout) したものに関しては、以下のようにターミナルに表示されていると思われる。

(<UserCheckout:入力したメアド>, False)

get_or_createは、getした場合、[0]にgetの内容、[1]に、createされたかどうかのbooleanが返される。そのため、user_checkout, created = UserCheckout.objects.get_or_create(email=email) で、createdに、createのtrue,falseを代入しておく。

carts/view.py のCheckoutViewに、sessionプロパティを追加する。

postして、formがvalidだった場合に、session[user_checkout_id] に、user_checkout.id を代入する。そうすることで、sessionから、UserCheckoutのidをゲットできるようになる。

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        form = self.get_form()
        if form.is_valid():
            email = form.cleaned_data.get("email")
            user_checkout, created = UserCheckout.objects.get_or_create(email=email)
            request.session["user_checkout_id"] = user_checkout.id
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

引き続き、checkoutViewを編集

class CheckoutView(FormMixin, DetailView):
...

    def get_context_data(self, *args, **kwargs):
        context = super(CheckoutView, self).get_context_data(*args, **kwargs)
        user_can_continue = False
        user_check_id = self.request.session.get["user_checkout_id"]
        if not self.request.user.is_authenticated() or user_check_id == None:# or if request.user.is_guest:
            context["login_form"] = AuthenticationForm()
            context["next_url"] = self.request.build_absolute_uri()
        elif self.request.user.is_authenticated() or user_check_id != None:
            user_can_continue = True
        else:
            pass
        context["user_can_continue"] = user_can_continue
        context["form"] = self.get_form()
        return context

ポイント

  • user_check_id = self.request.session.get["user_checkout_id"] は、postでuser_checkout_idをゲットしてる場合と、そうでない場合は分けている。

  • ユーザーがログインしていない、もしくは、user_check_idがnoneの場合は、ログインフォームを表示する

  • ユーザーがログインしているもしくは、user_check_idになにかが入っている場合は、user_can_continue = True

気づき・課題など

form methodの、clean_フィールド名は、is_valid()の時に実行されるfunctionなのかもしれんな。