Django e-commerce part61 Crafting the order Part 1
order 処理を完成させる
orders/models.py のOrderを修正する。
from django.db.models.signals import pre_save class Order(models.Model): ... def order_pre_save(sender, instance, *args, **kwargs): shipping_total_price = instance.shipping_total_price cart_total = instance.cart.total order_total = shipping_total_price + cart_total instance.order_total = order_total pre_save.connect(order_pre_save, sender=Order)
pre_save signalが、Orderから送られてきたら、order_pre_save が発動する。
これにより、前章のerrorが解消されう。
orders/models.py のOrderを少し修正する。
class Order(models.Model): cart = models.ForeignKey(Cart) user = models.ForeignKey(UserCheckout) billing_address = models.ForeignKey(UserAddress, related_name='billing_address') shipping_address = models.ForeignKey(UserAddress, related_name='shipping_address') shipping_total_price = models.DecimalField(max_digits=50, decimal_places=0, default=1000) order_total = models.DecimalField(max_digits=50, decimal_places=0)
carts/views.py のcheckoutviewを少し修正
... new_order_id = request.session.get("order_id")#代入するときは、[]でkeyを指定。取り出すときは、get("")でキーを指定 if new_order_id is None: new_order = Order.objects.create(cart=cart) request.session.get["order_id"] = new_order.id else: new_order = Order.objects.get(id=new_order_id) new_order.cart = cart new_order.user = user_checkout new_order.billing_address = billing_address new_order.shipping_address = shipping_address new_order.save() return get_data ...
ポイント
- new_order_id があるかどうかで、処理を分岐させる。(なかったら新たに作る)
carts/views.py にget_order() メソッドを設定する。
class CheckoutView(FormMixin, DetailView): model = Cart template_name = "carts/checkout_view.html" form_class = GuestCheckoutForm def get_order(self, *args, **kwargs): 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.get["order_id"] = new_order.id else: new_order = Order.objects.get(id=new_order_id) return new_order ... def get(self, request, *args, **kwargs): get_data = super(CheckoutView, self).get(request, *args, **kwargs) cart = self.get_object() order = self.get_order() ...
このままでは、'AnonymousUser' object has no attribute 'email'
が出てしまうので、ここを後で修正する。
ポイント
- get_oderの、requestには、selfをつける。引数にrequestは入らないため。
orders/views.py のget_formに少し問題あり。
以下にエラーが出ているので修正する。
user__email=self.request.user.email,
一時的に以下のようにしてみる。
def get_form(self, *args, **kwargs): form = super(AddressSelectFormView, self).get_form(*args, **kwargs) try: form.fields["billing_address"].queryset = UserAddress.objects.filter( user__email=self.request.user.email, type='billing', ) form.fields["shipping_address"].queryset = UserAddress.objects.filter( user__email=self.request.user.email, type='shipping', ) except: pass return form
try, exceptで、passしてみる。
このエラーの原因は、anonymous userだと、user__email=self.request.user.email
この部分のuserの部分は、
AddressForm
-> UserAddress
-> user(UserCheckout)
-> UserCheckout user = settings.AUTH_USER_MODEL
となっており、登録したuserでないと、errorが出てしまう。
疑問点
- orderは、userが必須のため、上記のコードだとuserの箇所でerrorが出てしまう。確かに、userは入ってないので、多分駄目だと思うけど、なぜか動画ではerrorが出ていない。と思ったら、こちらの見落としで、model user null=True担っていた。