Djangoroidの奮闘記

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

Django e-commerce part71 Order Detail

Order Detail Viewを、class based viewで作成

orders/views.py に OrderDetail viewを作成

from django.views.generic.detail import DetailView
...
class OrderDetail(DetailView):
    model = Order
...

urls.py を設定する。

    url(r'^orders/(?P<pk>\d+)/$', OrderDetail.as_view(), name='orders_detail'),

このままでは、orders/order_detail.html が存在しないとなってしまうので、作成する。

order_detail.htmlを作成

{% extends "base.html" %}


{% block content %}


{% endblock %}

checkout_detailに似ているため、それを利用して編集していく。

order_summary_short.html を作成する。

include用に、order_summary_short.htmlを作成する。

<p class='lead'>
    注文内容を確認する </p>

<table class='table'>
<tr><td>{{ order.cart.cartitem_set.count }} 商品: <br/>{% for i in order.cart.cartitem_set.all %}
<b>{{ i.item.get_title }}</b></tr><br/>
{% endfor %}
</td></tr>
<tr><td>カート内合計金額(税別): {{order.cart.subtotal }}</td></tr>
<tr><td>消費税: {{order.cart.tax_total }}</td></tr>
<tr><td>商品代金合計(税込): {{order.cart.total }}</td></tr>
<tr><td>送料: {{order.shipping_total_price }}</td></tr>
<tr><td>合計(税込): {{order.order_total }}</td></tr>

</table>
</div>

<div class='col-sm-4 col-sm-offset-4 text-center'>
<p><b>請求先住所:</b>
<br/>
{{ order.billing_address.get_address }}
</p>
<p><b>送付先住所:</b>
<br/>
{{ order.shipping_address.get_address }}
</p>

order_detai.htmlを編集

{% extends "base.html" %}


{% block content %}

{% include "orders/order_summary_short.html" with order=object %}

{% endblock %}
  • ここでいう、objectは、contextで渡されるOrderのインスタンス。。。なはず。

orders/views.py にloginrequiredmixinを継承する。

class OrderDetail(LoginRequiredMixin, DetailView):
    model = Order

ただこれだけでは、ログイン認証だけで、個別のページにはなっていない。そのため、個別のページはuserとして登録されているorderしか表示されないように設定する。そのためには、dispatchを設定する。

orders/views.py に、dispatchでユーザーのみのページを表示する。

まず、準備として、クラスメソッドのdispatchを上書きする。

class OrderDetail(LoginRequiredMixin, DetailView):
    model = Order

    def dispatch(self, request, *args, **kwargs):
        if request.user.is_authenticated():
            return super(OrderDetail, self).dispatch(request, *args, **kwargs)
        else:
            raise Http404
  • この段階ではまだユーザー認証のみ。

クラスメソッドのdispatch をさらに編集する。

class OrderDetail(LoginRequiredMixin, DetailView):
    model = Order

    def dispatch(self, request, *args, **kwargs):
        try:
            user_check_id = self.request.session.get("user_checkout_id")
            user_checkout = UserCheckout.objects.get(id=user_check_id)
        except:
            user_checkout = None

        obj = self.get_object()
        if obj.user_checkout == user_checkout and user_checkout is not None:
            return super(OrderDetail, self).dispatch(request, *args, **kwargs)
        else:
            raise Http404

ポイント

  • user_check_id に、sessionにあるuser_checkout_idを代入する。(user_checkout_idは、UserCheckout.id)
  • user_checkoutは、上記のidで、絞り込んだUserCheckoutのインスタンス(UserCheckout())
  • もし、noneとかでerrorが出たら、user_checkoutには、Noneを代入する。
  • get_objectは、クラスメソッドなはず。Order(pk=?)のインスタンスをゲットする。つまりobj =self.get_object()は、objに、pkで絞り込んだOrder()のインスタンスを渡している。
  • obj.user_checkout ??? ここは Order().user_checkout という感じになるが、それはattributeerrorが発生しそうな予感。
  • とにかく、pkで絞り込んだOrder()のuserと、ログインuserが一緒ならOKという処理がしたいと思われる。

carts/views.py のredirect先を修正する。

class CheckoutFinalView(CartOrderMixin, View):
    def post(self, request, *args, **kwargs):
        order = self.get_order()
        if request.POST.get("payment_token") == "ABC":
            order.mark_completed()
            del request.session["cart_id"]
            del request.session["order_id"]
        return redirect("orders_detail", pk=order.pk)
  • redirect 先には、pk=order.pkを代入して表示させる。

やはり、attribute errorが出たので、修正する。orders/views.py

class OrderDetail(LoginRequiredMixin, DetailView):
    model = Order

    def dispatch(self, request, *args, **kwargs):
        try:
            user_check_id = self.request.session.get("user_checkout_id")# user_checkout.id
            user_checkout = UserCheckout.objects.get(id=user_check_id)
        except UserCheckout.DoesNotExist:# checkout.idがない時は、userで、Usercheckout()を絞り込む
            user_checkout = UserCheckout.objects.get(user=request.user)
        except:
            user_checkout = None
        print (user_checkout)
        obj = self.get_object()#obj=Order()
        if obj.user == user_checkout and user_checkout is not None:
            return super(OrderDetail, self).dispatch(request, *args, **kwargs)
        else:
            raise Http404

ゲストユーザーで登録すると、注文確定後に、redirectテストをする。

http://127.0.0.1:8000/accounts/login/?next=/orders/26/

という感じのurlにアクセスして、ログイン画面が出てしまう。

そのため、OderDetailのLoginRequiredMixinを削除して、再送する。

これで注文確定後に、注文内容が表示される。