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なのかもしれんな。