更改反映在订单摘要中错误项目中的变体数量

A_K*_*A_K 7 python django django-views

我对订单摘要页面中的变化和与之相关的数量有疑问。

它工作完美,突然之间(这是一个简化的例子):

当我将 2 件商品添加到购物车时:

  • 小号的商品 X
  • 中号商品 X

当我更改商品 X 大小中号的数量时,此更改反映在最先选择的商品 X 大小小中。

在订单汇总中,模板中有一个加减号来改变数量。

我已经确定了问题,但我无法弄清楚它为什么会发生

这是模板:

{% block content %}
    <main>
        <div class="container">
        <div class="table-responsive text-nowrap" style="margin-top:90px">
        <h2> Order Summary</h2>
        <table class="table">
            <thead>
            <tr>
                <th scope="col">#</th>
                <th scope="col">Item Title</th>
                <th scope="col">Price</th>
                <th scope="col">Quantity</th>
                <th scope="col">Size</th> 
                <th scope="col">Total Item Price</th>
            </tr>
            </thead>
            <tbody>
            {% for order_item in object.items.all %}
            <tr>
                <th scope="row">{{ forloop.counter }}</th>
                <td>{{ order_item.item.title }}</td>
                <td>{{ order_item.item.price }}</td>
                <td>
                <a href="{% url 'core:remove-single-item-from-cart' order_item.item.slug %}"><i class="fas fa-minus mr-2"></a></i>
                {{ order_item.quantity }}
                <a href="{% url 'core:add-to-cart' order_item.item.slug %}"><i class="fas fa-plus ml-2"></a></i>
                </td>                
                <td>
                {% if order_item.variation.all %}
                {% for variation in order_item.variation.all %}
                {{ variation.title|capfirst }}
                {% endfor %}
                {% endif %}
                </td> 
                <td>
                {% if order_item.item.discount_price %}
                    $ {{ order_item.get_total_discount_item_price }}
                    <span class="badge badge-primary" style="margin-left:10px">Saving ${{ order_item.get_amount_saved }}</span>
                {% else %}
                    $ {{ order_item.get_total_item_price }}
                {% endif %}
                <a style="color:red" href="{% url 'core:remove-from-cart' order_item.item.slug %}">
                <i class="fas fa-trash float-right"></i>
                </a>
                </td>
            </tr>
            {% empty %}
            <tr>
                <td colspan='5'>Your Cart is Empty</td>
            </tr>
            <tr>
                <td colspan="5">
                <a class='btn btn-primary float-right ml-2'href='/'>Continue Shopping</a>
            </tr>                
            {% endfor %}
            {% if object.coupon %}
            <tr>
                <td colspan="4"><b>Coupon</b></td>
                <td><b>-${{ object.coupon.amount }}</b></td>
            </tr>            
            {% endif %}
            <tr>
                <td colspan="5"><b>Sub total</b></td>
                <td><b>${{ object.get_total }}</b></td>
            </tr>
            <tr>
                <td colspan="5">Taxes</td>
                <td>${{ object.get_taxes|floatformat:2  }}</td>
            </tr>
            {% if object.grand_total %}
            <tr>
                <td colspan="5"><b>Grand Total</b></td>
                <td><b>${{ object.grand_total|floatformat:2 }}</b></td>
            </tr>
            <tr>
                <td colspan="6">
                <a class='btn btn-primary float-right ml-2'href='/'>Continue Shopping</a>
                <a class='btn btn-warning float-right'href='/checkout/'>Proceed to Checkout</a></td>
            </tr> 
            {% endif %}                          
            </tbody>
        </table>
        </div>
        </div>
    </main>
    <!--Main layout-->
{% endblock content %} 
Run Code Online (Sandbox Code Playgroud)

这是views.py

class OrderSummaryView(LoginRequiredMixin, View):
    def get(self, *args, **kwargs):

        try:
            order = Order.objects.get(user=self.request.user, ordered=False)
            context = {
                'object': order
            }
            return render(self.request, 'order_summary.html', context)
        except ObjectDoesNotExist:
            messages.warning(self.request, "You do not have an active order")
            return redirect("/")


@login_required
def add_to_cart(request, slug):
    item = get_object_or_404(Item, slug=slug)

    order_item_qs = OrderItem.objects.filter(
        item=item,
        user=request.user,
        ordered=False
    )

    item_var = []  # item variation
    if request.method == 'POST':
        for items in request.POST:
            key = items
            val = request.POST[key]
            try:
                v = Variation.objects.get(
                    item=item,
                    category__iexact=key,
                    title__iexact=val
                )
                item_var.append(v)
            except:
                pass

        if len(item_var) > 0:
            for items in item_var:
                order_item_qs = order_item_qs.filter(
                    variation__exact=items,
                )

    if order_item_qs.exists():
        order_item = order_item_qs.first()
        order_item.quantity += 1
        order_item.save()
    else:
        order_item = OrderItem.objects.create(
            item=item,
            user=request.user,
            ordered=False
        )
        order_item.variation.add(*item_var)
        order_item.save()

    order_qs = Order.objects.filter(user=request.user, ordered=False)
    if order_qs.exists():
        order = order_qs[0]
        # check if the order item is in the order
        if not order.items.filter(item__id=order_item.id).exists():
            order.items.add(order_item)
            messages.info(request, "This item quantity was updated.")
            return redirect("core:order-summary")
    else:
        ordered_date = timezone.now()
        order = Order.objects.create(
            user=request.user, ordered_date=ordered_date)
        order.items.add(order_item)
        messages.info(request, "This item was added to cart.")
        return redirect("core:order-summary")


@login_required
def remove_from_cart(request, slug):
    item = get_object_or_404(Item, slug=slug)
    order_qs = Order.objects.filter(
        user=request.user,
        ordered=False
    )
    if order_qs.exists():
        order = order_qs[0]
        # check if the order item is in the order
        if order.items.filter(item__slug=item.slug).exists():
            order_item = OrderItem.objects.filter(
                item=item,
                user=request.user,
                ordered=False
            )[0]
            order.items.remove(order_item)
            order_item.delete()
            messages.info(request, "This item was removed from your cart")
            return redirect("core:order-summary")

        else:
            messages.info(request, "This item was not in your cart")
            return redirect("core:product", slug=slug)
    else:
        messages.info(request, "You don't have an active order")
        return redirect("core:product", slug=slug)


@login_required
def remove_single_item_from_cart(request, slug):
    item = get_object_or_404(Item, slug=slug)
    order_qs = Order.objects.filter(
        user=request.user,
        ordered=False
    )
    if order_qs.exists():
        order = order_qs[0]
        # check if the order item is in the order
        if order.items.filter(item__slug=item.slug).exists():
            order_item = OrderItem.objects.filter(
                item=item,
                user=request.user,
                ordered=False
            )[0]
            if order_item.quantity > 1:
                order_item.quantity -= 1
                order_item.save()
            else:
                order.items.remove(order_item)
            messages.info(request, "This item quantity was updated")
            return redirect("core:order-summary")
        else:
            messages.info(request, "This item was not in your cart")
            return redirect("core:product", slug=slug)
    else:
        messages.info(request, "You do not have an active order")
        return redirect("core:product", slug=slug)
# End Remove Items (Products removed from Cart)
Run Code Online (Sandbox Code Playgroud)

这是models.py


class Item(models.Model):
    title             = models.CharField(max_length=100)
    -------------------------------------------------------------------------
    updated           = models.DateTimeField(auto_now_add=False, auto_now=True)
    active            = models.BooleanField(default=True)

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse("core:product", kwargs={
            'slug': self.slug
        })

    def get_add_to_cart_url(self):
        return reverse("core:add-to-cart", kwargs={
            'slug': self.slug
        })

    def get_remove_from_cart_url(self):
        return reverse("core:remove-from-cart", kwargs={
            'slug': self.slug
        })


class VariationManager(models.Manager):
    def all(self):
        return super(VariationManager, self).filter(active=True)

    def sizes(self):
        return self.all().filter(category='size')

    def colors(self):
        return self.all().filter(category='color')


VAR_CATEGORIES = (
    ('size', 'size',),
    ('color', 'color',),
    ('package', 'package'),
)


class Variation(models.Model):
    item = models.ForeignKey(Item, on_delete=models.CASCADE)
    category = models.CharField(
        max_length=120, choices=VAR_CATEGORIES, default='size')
    title = models.CharField(max_length=120)
    image = models.ImageField(null=True, blank=True)
    price = models.DecimalField(
        decimal_places=2, max_digits=100, null=True, blank=True)
    objects = VariationManager()
    active = models.BooleanField(default=True)

    def __str__(self):
        return self.title

class OrderItem(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             on_delete=models.CASCADE)
    ordered = models.BooleanField(default=False)
    item = models.ForeignKey(Item, on_delete=models.CASCADE)
    quantity = models.IntegerField(default=1)
    variation = models.ManyToManyField(Variation)

    def __str__(self):
        return f"{self.quantity} of {self.item.title}"
Run Code Online (Sandbox Code Playgroud)

Moh*_*mar 5

我检查了你的代码。在您的代码中,您正在获取项目,然后更改数量。尺寸较大的物品X和尺寸较小的物品X,我觉得两者都代表同一个物品。因此,更改 1 个项目将反映在具有不同大小的同一项目中。您有什么方法可以根据 item_id 和大小来识别项目吗?

OrderItem.objects.filter(
                item=item,
                user=request.user,
                ordered=False
            )[0].
Run Code Online (Sandbox Code Playgroud)

OrderItem.objects.filter(
                item=item,
                user=request.user,
                size=item.size
                ordered=False
            )[0].
Run Code Online (Sandbox Code Playgroud)

像添加尺寸 = S 或 L 之类的东西,会有所作为。此外,您正在获取第一个元素(使用数组 [0])。如果有两个项目具有相同的数据,您可能正在执行操作或错误的项目。如果项目是唯一的,您可以使用 get 代替过滤器。