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

Djangoroidの奮闘記

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

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担っていた。