[英]Adding products to cart not working properly
我遇到了代码问题,更具体地说是一个错误,即当我第一次将商品添加到购物车时(有变体,比如说绿色和中等),它被很好地添加了。 然后当我添加另一个项目(比如说蓝色和小号)时,它也可以工作。 但是,当我从order_summary.html
增加项目数量时,它增加了另一个项目的数量,而不是我点击的那个(如果我点击红色和中,蓝色和大的数量增加)并说:请指定所需的变化。 为什么会这样? 还值得注意的是,当我从我的单个产品页面添加具有相同变体的相同项目时,它工作正常。 我认为这个错误的发生是因为我的观点是写的。 我试图自己解决它,但我迷路了。 谁能帮帮我? 提前致谢!
我的模型.py:
class Item(models.Model):
title = models.CharField(max_length=120)
price = models.FloatField()
class Variation(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE)
name = models.CharField(max_length=50) # size, color
class ItemVariation(models.Model):
variation = models.ForeignKey(Variation, on_delete=models.CASCADE)
value = models.CharField(max_length=50) # small, medium large etc
class OrderItem(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
item_variations = models.ManyToManyField(ItemVariation)
quantity = models.IntegerField(default=1)
ordered = models.BooleanField(default=False)
class Order(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
ref_code = models.CharField(max_length=20)
ordered = models.BooleanField(default=False)
items = models.ManyToManyField(OrderItem)
start_date = models.DateTimeField(auto_now_add= True)
ordered_date = models.DateTimeField()
我的意见.py:
@login_required
def add_to_cart(request, slug):
item = get_object_or_404(Item, slug=slug)
variations = request.POST.getlist('variations', [])
print(variations)
print(request.POST)
minimum_variation_count = Variation.objects.filter(item=item).count()
print(minimum_variation_count)
print(len(variations))
if len(variations) < minimum_variation_count:
messages.info(request, "Please specify the required variations.")
order_item_qs = OrderItem.objects.filter(
item=item,
user= request.user,
ordered=False,
)
for v in variations:
print(v)
order_item_qs = order_item_qs.filter(
item_variations__value=v
)
if order_item_qs.exists():
order_item = order_item_qs.first()
order_item.quantity += 1
# messages.success(request, "Product quantity was updated.")
order_item.save()
else:
order_item = OrderItem.objects.create(
item=item,
user= request.user,
ordered=False,
)
# order_item.item_variations.add(*variations)
item_variations_to_add = ItemVariation.objects.filter(
variation__item=item,
value__in=variations
).values_list('id', flat=True)
order_item.item_variations.add(*item_variations_to_add)
order_item.save()
order_qs = Order.objects.filter(user=request.user, ordered=False)
if order_qs.exists():
order = order_qs[0]
if not order.items.filter(item__id=order_item.id).exists():
order.items.add(order_item)
# print(request.POST.getlist('variations', None))
messages.success(request, "Product added to cart.")
return redirect("order-summary")
else:
ordered_date = timezone.now()
order = Order.objects.create(user=request.user, ordered_date=ordered_date)
order.items.add(order_item)
# print(request.POST.getlist('variations', None))
messages.success(request, "Product added to cart.")
return redirect("order-summary")
return redirect("order-summary")
@login_required
def remove_single_item_from_cart(request, slug):
item = get_object_or_404(Item, slug=slug)
variations = request.POST.getlist('variations', [])
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()
messages.info(request, "Product quantity was updated.")
else:
order.items.remove(order_item)
order_item.delete()
messages.info(request, "Product was removed from cart.")
return redirect("order-summary")
else:
messages.info(request, "Product was not in your cart")
return redirect("product", slug=slug)
else:
messages.info(request, "You do not have an active order")
return redirect("product", slug=slug)
return redirect("order-summary")
我的 order_summary.html (我可以增加数量):
<th scope="row" class="border-0">
<div class="p-2">
<img src="{{ order_item.item.image_url }}" alt="" width="70" class="img-fluid rounded shadow-sm">
<div class="ml-3 d-inline-block align-middle">
<h5 class="mb-1"> <a href="{{ order_item.item.get_absolute_url }}" class="text-dark
-inline-block align-middle">{{ order_item.item.title }}</a>
{% for var in order_item.item_variations.all %}
<!-- <h6>{{ order_item.item_variations.all }}</h6> -->
<!-- <ul> -->
<!-- <li><h6>{{ var.variation.name }}: {{ var.value }}</h6></li> -->
<!-- </ul> -->
<h6>{{ var.variation.name }}: {{ var.value }}</h6>
{% endfor %}
</div>
</div>
</th>
{% if order_item.item.discount_price %}
<td class="border-0 align-middle"><strong>${{ order_item.get_total_discount_item_price }} <span class="badge badge-warning">Saving ${{ order_item.get_amount_saved }}</span></strong></td>
{% else %}
<td class="border-0 align-middle"><strong>${{ order_item.get_total_item_price }}</strong></td>
{% endif %}
<td class="border-0 align-middle"><strong>
<div class="pull-center">
<a href="{% url 'remove-single-item-from-cart' order_item.item.slug %}" class="btn mr-2"><i class="fa fa-minus"></i></a>
{{ order_item.quantity }}<a href="{% url 'add-to-cart' order_item.item.slug %}" class="btn ml-2"><i class="fa fa-plus"></i></a>
</div>
</div>
</strong></td>
<td class="border-0 align-middle"><a href="{% url 'remove-from-cart' order_item.item.slug %}" class="text-dark"><i class="fa fa-trash"></i></a></td>
</tr>
我的 single_product.html (我可以从这里增加我的产品数量,它工作正常):
<form class="form" method="POST" action="{{ object.get_add_to_cart_url }}">
{% csrf_token %}
{% for var in object.variation_set.all %}
<h5>Choose {{ var.name }}</h5>
<select class="form-control mb-4 col-md-4" name="variations">
{% for item in var.itemvariation_set.all %}
<option value="{{ item.value }}">{{ item.value|capfirst }}</option>
{% endfor %}
</select>
{% endfor %}
<div class="action">
<button class="btn btn-success">Add to Cart</button>
<button class="like btn btn-danger" type="button"><span class="fa fa-heart"></span></button>
</div>
</form>
我的管理员.py:
from django.contrib import admin
from .models import Item, Variation, ItemVariation
class ItemVariationAdmin(admin.ModelAdmin):
list_display = ['variation',
'value']
list_filter = ['variation', 'variation__item']
search_fields = ['value']
class ItemVariationInLineAdmin(admin.TabularInline):
model = ItemVariation
extra = 1
class VariationAdmin(admin.ModelAdmin):
list_display = ['item',
'name']
list_filter = ['item']
search_fields = ['name']
inlines = [ItemVariationInLineAdmin]
admin.site.register(Item)
admin.site.register(ItemVariation, ItemVariationAdmin)
admin.site.register(Variation, VariationAdmin)
我的 urls.py:
path('add_to_cart/<slug>/', orders_views.add_to_cart, name='add-to-cart'),
path('remove_from_cart/<slug>/', orders_views.remove_from_cart, name='remove-from-cart'),
variations
为空,因为您没有通过 POST 请求发送,也没有从您的 html 表单发送任何变体输入。 这就是为什么您会收到"Please specify the required variations."
信息。 ( len(variations) == 0
)variations
是空的,因为变量中for v in variations
没有做任何过滤工作。 因此,当您到达order_item_qs.first()
时,您不一定会获得您期望的 OrderItem,并且可能在错误的 OrderItem 上为+=1
。修理:
increase_quantity
url 端点,您可以在其中将 OrderItem id 传递到视图中。 然后您就可以确切地知道要增加数量的 OrderItem 并且不需要进行任何过滤来找到它。如果您不想更改视图,您的order_summary.html
需要为每个 OrderItem 提供一个表单,以便在更改数量时发布相关变化。
在order_summary.html
中,靠近底部,替换这个:
<div class="pull-center">
<a href="{% url 'remove-single-item-from-cart' order_item.item.slug %}" class="btn mr-2"><i class="fa fa-minus"></i></a>
{{ order_item.quantity }}<a href="{% url 'add-to-cart' order_item.item.slug %}" class="btn ml-2"><i class="fa fa-plus"></i></a>
</div>
</div>
像这样:
<div class="pull-center">
<form method="POST" action="{% url 'add-to-cart' order_item.item.slug %}">
{% csrf_token %}
<a href="{% url 'remove-single-item-from-cart' order_item.item.slug %}" class="btn mr-2"><i class="fa fa-minus"></i></a>
{{ order_item.quantity }}<button type="submit" class="btn ml-2"><i class="fa fa-plus"></i></button>
{% for iv in order_item.item_variations.all %}
<input type="hidden" name="variations" value="{{ iv.value }}">
{% endfor %}
</form>
</div>
您需要确保模板的这一部分尚未包含在表单中。
您在评论中提到您现在需要增加和减少 OrderItem 数量的解决方案。 是时候采取不同的方法了。
该解决方案提供了一个视图来处理订购商品数量(正数和负数)的变化。 它使用OrderItem
主键,这比 Item.pk 和变体的组合更可靠。
将此添加到views.py
:
@login_required
def update_qty(request):
if request.method == 'POST':
item_slug = request.POST.get('item_slug', None)
# Check for an order_item
order_item_pk = request.POST.get('order_item', None)
order_item = OrderItem.objects.filter(pk=order_item_pk).first()
if not order_item:
messages.info(request, "Product was not in your cart")
return redirect("product", slug=item_slug)
# Check for an active order
order = Order.objects.filter(user=request.user, ordered=False).first()
if not order:
messages.info(request, "You do not have an active order")
return redirect("product", slug=item_slug)
# Check that order_item is in active order
if not order_item.order == order:
messages.info(request, "Product was not in your cart")
return redirect("product", slug=slug)
# Update quantities
action = request.POST.get('action', None)
if action == "plus":
order_item.quantity += 1
order_item.save()
messages.info(request, "Product quantity was updated.")
elif action == "minus":
order_item.quantity -= 1
if order_item.quantity < 1:
order_item.delete()
messages.info(request, "Product was removed from cart.")
else
order_item.save()
messages.info(request, "Product quantity was updated.")
return redirect("order-summary")
将此添加到您的urls.py
:
path('update-qty', orders_views.update_qty, name='update-qty'),
在order_summary.html
中,靠近底部,替换这个:
<div class="pull-center">
<a href="{% url 'remove-single-item-from-cart' order_item.item.slug %}" class="btn mr-2"><i class="fa fa-minus"></i></a>
{{ order_item.quantity }}<a href="{% url 'add-to-cart' order_item.item.slug %}" class="btn ml-2"><i class="fa fa-plus"></i></a>
</div>
</div>
像这样:
<div class="pull-center">
<form method="POST" action="{% url 'update-qty' %}">
{% csrf_token %}
<button type="submit" name="action" value="minus" class="btn mr-2"><i class="fa fa-minus"></i></button>
{{ order_item.quantity }}<button type="submit" name="action" value="plus" class="btn ml-2"><i class="fa fa-plus"></i></button>
<input type="hidden" name="item_slug" value="{{ order_item.item.slug }}">
<input type="hidden" name="order_item" value="{{ order_item.pk }}">
</form>
</div>
我认为您的问题在视图中
@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("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("order-summary")
而不是项目变化我会 go 作为变化经理
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',),
)
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)
objects = VariationManager()
active = models.BooleanField(default=True)
def __str__(self):
return self.title
对于模板
{% if order_item.variation.all %}
{% for variation in order_item.variation.all %}
{{ variation.title|capfirst }}
{% endfor %}
{% endif %}
这应该工作
我宁愿建议在任何应用程序代码中对 CRUD 视图使用基于类的视图 [通用] / 基于类的普通视图。 基于函数的视图对于简单的基于 CRUD 的视图来说太多了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.