【问题标题】:add to cart using django rest framework使用 django rest 框架添加到购物车
【发布时间】:2018-11-29 00:35:32
【问题描述】:

我正在考虑创建一个生产就绪的电子商务应用程序。但是我被困在添加到购物车功能中。我认为,要将产品添加到购物车,需要的是产品对象和数量。我已经创建了序列化器 CartSerializer 和 CartItemSerializer 以及 APIView 部分,但我很困惑要使用哪个序列化器,或者我必须制作一个不同的序列化器,它只有产品对象和数量的字段才能发布。因为使用我的代码,我得到了所有字段。

这是我的代码

class Cart(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.CASCADE)
    items = models.ManyToManyField(Cycle, through='CartItem')
    updated = models.DateTimeField(auto_now_add=False, auto_now=True)
    subtotal = models.DecimalField(max_digits=50, decimal_places=2, default=0.00)
    tax_percentage = models.DecimalField(max_digits=10, decimal_places=5, default=0.085)
    tax_total = models.DecimalField(max_digits=50, decimal_places=2, default=0.00)
    total = models.DecimalField(max_digits=50, decimal_places=2, default=0.00)
    active = models.BooleanField(default=True)
    objects = CartManager()

    def __str__(self):
        return str(self.id)


class CartItem(models.Model):
    cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
    item = models.ForeignKey(Cycle, on_delete=models.CASCADE)
    quantity = models.PositiveIntegerField(default=1)
    line_item_total = models.DecimalField(max_digits=10, decimal_places=2)

    def __str__(self):
        return self.cart.id


serializers.py


class CartSerializer(serializers.ModelSerializer):
    product = serializers.SerializerMethodField()

    class Meta:
        model = Cart
        fields = '__all__'

    @staticmethod
    def get_product(obj):
        return obj.product.name


class CartItemSerializer(serializers.ModelSerializer):
    item = serializers.SerializerMethodField()
    item_title = serializers.SerializerMethodField()
    product = serializers.SerializerMethodField()
    price = serializers.SerializerMethodField()

    class Meta:
        model = CartItem
        fields = [
            "item",
            "item_title",
            "price",
            "product",
            "quantity",
            "line_item_total",
        ]


views.py 

class CartAPIView(CartTokenMixin, CartUpdateAPIMixin, APIView):
    serializer_class = CartSerializer
    token_param = "token"
    cart = None

    def get_cart(self):
        data, cart_obj, response_status = self.get_cart_from_token()
        if cart_obj == None or not cart_obj.active:
            cart = Cart()
            cart.tax_percentage = 0.075
            if self.request.user.is_authenticated:
                cart.user = self.request.user
            cart.save()
            data = {
                "cart_id": str(cart.id)
            }
            self.create_token(data)
            cart_obj = cart

        return cart_obj

    def get(self, request, format=None):
        cart = self.get_cart()
        self.cart = cart
        self.update_cart()
        # token = self.create_token(cart.id)
        items = CartItemSerializer(cart.cartitem_set.all(), many=True)
        cart.items.all()
        data = {
            "token": self.token,
            "cart": cart.id,
            "total": cart.total,
            "subtotal": cart.subtotal,
            "tax_total": cart.tax_total,
            "count": cart.items.count(),
            "items": items.data,
        }
        return Response(data)

    @staticmethod
    def post(self, request, format=None):
        product_id = request.POST.get('product_id', None)
        if product_id is not None:
            try:
                product_obj = Cycle.objects.get(id=product_id)
            except Cycle.DoesNotExist:
                pass
            cart_instance, created = Cart.objects.new_or_get(request)
            if product_obj in cart_instance.items.all():
                cart_instance.items.remove(product_obj)
                added = False
            else:
                cart_instance.items.add(product_obj)
                added = True
            request.session['cart_items'] = cart_instance.items.count()
            data = {
                "added": added,
                "removed": not added,
                "cartItemCount": cart_instance.items.count()
            }
            return Response(data, status.HTTP_200_OK)

谁能帮我完美地连接序列化器和apiview?

【问题讨论】:

    标签: python django django-rest-framework django-views


    【解决方案1】:

    请参阅Django gitter 频道中的对话。我简化了您的代码,这是我对您的问题的尝试。

    carts/models.py

    from django.contrib.auth import get_user_model
    from django.db import models
    
    from items.models import Item
    
    User = get_user_model()
    
    
    class Cart(models.Model):
        """Let Cart be a meta. And order_items is reverse relation"""
        created_by = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)
        subtotal = models.DecimalField(max_digits=50, decimal_places=2, default=0.00)
        tax_percentage = models.DecimalField(max_digits=10, decimal_places=5, default=0.085)
        tax_total = models.DecimalField(max_digits=50, decimal_places=2, default=0.00)
        total = models.DecimalField(max_digits=50, decimal_places=2, default=0.00)
        # Use ORM here to help you get the count() of each item
        # 1 item represent 1 qty
        order_items = models.ManyToManyField(Item)
    

    items/models.py

    class Item(models.Model):
        """
        Represent the product in the system. Because I start the coding from `Cart`
        Therefore I put it as an `item`.
        """
        name = models.CharField(max_length=255)
    

    carts/serializers.py

    from rest_framework import serializers
    
    from carts.models import Cart
    
    
    class CartSerializer(serializers.ModelSerializer):
        created_by = serializers.CurrentUserDefault()
    
        class Meta:
            model = Cart
            fields = [
                'created_by',
                'order_items',
                'subtotal',
                'tax_percentage',
                'tax_total',
                'total',
            ]
    

    carts/viewsets.py

    from rest_framework import viewsets
    from rest_framework.permissions import IsAuthenticated
    
    from carts.api.serializers import CartSerializer
    from carts.models import Cart
    
    
    class CartViewSet(viewsets.ModelViewSet):
        permission_classes = (IsAuthenticated,)
        queryset = Cart.objects.all()
        serializer_class = CartSerializer
    

    由于您的模型是M2M 嵌套order_items 是现成的。而且created_by 用户也很常见。你可以重复使用serializers.CurrentUserDefault() 我曾经读过答案提到我get_user_model() 更安全,因为它返回一个对象。但是settings.AUTH_USER_MODEL 返回字符串。如果你对此没有问题,你可以忽略。 (如果我错了也请纠正我)

    如果我的回答不准确,请告诉我。我会尽力再做一遍。

    猜你喜欢
    • 2021-01-10
    • 2021-05-23
    • 1970-01-01
    • 2012-09-22
    • 1970-01-01
    • 2021-08-31
    • 2020-09-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多