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を削除して、再送する。
これで注文確定後に、注文内容が表示される。