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

Djangoroidの奮闘記

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

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を渡すのが一般的なのか?