Django e-commerce part66 Custom Mixin for Cart & order
Cart,OrderのMixinの作成
carts/views.py MixinViewを追加する。
CheckoutViewのget_orderと、get_objectを新しく作成したCartOrderMixinにコピペしてみる。(get_object()は、get_cartに名前を変えてある)
class CartOrderMixin(object): def get_order(self, *args, **kwargs): cart = self.get_cart() new_order_id = self.request.session.get("order_id") if new_order_id is None: new_order = Order.objects.create(cart=cart) self.request.session["order_id"] = new_order.id else: new_order = Order.objects.get(id=new_order_id) return new_order def get_cart(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
引き続き、views.pyのCheckoutViewを修正する。
class CheckoutView(CartOrderMixin, FormMixin, DetailView): ... def get_object(self, *args, **kwargs): cart = self.get_cart if cart == None: return None return cart
ポイント
- CartOrderMixin を継承する。
- get_objectには、get_cart()オブジェクトを組み込む。get_cart()で、cartのフィルタはかかっているためここでは、get_cart()で、ゲットしたオブジェクトを返すだけの関数にしておく。
ここで、うまく動作するかを確認しておく。
CartOrderMixinを、mixins.pyにそのまま移動させる。
from carts.models import Cart from .models import Order class CartOrderMixin(object): def get_order(self, *args, **kwargs): cart = self.get_cart() new_order_id = self.request.session.get("order_id") if new_order_id is None: new_order = Order.objects.create(cart=cart) self.request.session["order_id"] = new_order.id else: new_order = Order.objects.get(id=new_order_id) return new_order def get_cart(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
carts/views.pyにimportするのも忘れない。
from orders.mixins import CartOrderMixin
orders/views.py のAddressSelectFormViewを修正する。
送付先住所と請求先住所が、アドレスセレクトのform_validの時に保存されるように設定する。(現時点では、checkoutviewで、リロードしないと、表示されない。)
from .mixins import CartOrderMixin ... class AddressSelectFormView(CartOrderMixin, FormView): ... def form_valid(self, form, *args, **kwargs): billing_address = form.cleaned_data["billing_address"] shipping_address = form.cleaned_data["shipping_address"] order = self.get_order() order.billing_address = billing_address order.shipping_address = shipping_address order.save() # self.request.session["billing_address_id"] = billing_address.id # self.request.session["shipping_address_id"] = shipping_address.id return super(AddressSelectFormView, self).form_valid(form, *args, **kwargs)
- order.billing_address = billing_address、order.shipping_address = shipping_address、order.save()で、それぞれorderのインスタンスに代入して、save()する。
carts/views.py 不要な箇所をコメントアウトする
class CheckoutView(CartOrderMixin, FormMixin, DetailView): ... def get(self, request, *args, **kwargs): get_data = super(CheckoutView, self).get(request, *args, **kwargs) cart = self.get_object() new_order = self.get_order() user_checkout_id = request.session.get("user_checkout_id") if user_checkout_id != None: user_checkout = UserCheckout.objects.get(id=user_checkout_id) if new_order.billing_address_id == None or new_order.shipping_address_id == None: return redirect("order_address") new_order.user = user_checkout new_order.save() return get_data
mixins.py を少し修正する。
class CartOrderMixin(object): ... def get_cart(self, *args, **kwargs): cart_id = self.request.session.get("cart_id") if cart_id == None: return None # 重要 cart = Cart.objects.get(id=cart_id) if cart.items.count() == 0; return None return cart
get_cartで、cart_idがnoneの時と、cart.items.count が空の場合、return Noneを返すように設定しておく。後で、Noneが返り値の場合の、条件分岐処理を関連するviewに反映させていく。
carts/views.py
def get(self, request, *args, **kwargs): get_data = super(CheckoutView, self).get(request, *args, **kwargs) cart = self.get_object() if cart == None: return redirect("cart") new_order = self.get_order()
cart==Noneの時に、cart にredirectするように設定しておく。
carts/checkout_view.html に追記する。
<p> <a href='{% url "order_address" %}'>送付先/請求先住所を変更する</a> </p>
疑問点など
Mixinの場合は、objectを渡すのが一般的なのか?