In my cart i can add same product with different size and color.but randomly when i want to to add same product with different size and color i have this error in my cart iter function.i've tracked the process in debugger and found that it somehow traped in my Product model str method and finally this error raise.
models:
from django.db import modelsfrom django.urls import reversefrom django.conf import settingsfrom colorfield.fields import ColorFieldclass Product(models.Model): GENDER_MALE = 'm' GENDER_FEMALE = 'f' GENDER_BOTH = 'b' GENDER_CHOICE = [ (GENDER_MALE, 'Male'), (GENDER_FEMALE, 'Female'), (GENDER_BOTH, 'Both') ] name = models.CharField(max_length=200) category = models.CharField(max_length=200) gender = models.CharField(choices=GENDER_CHOICE, max_length=1) sizes = models.ManyToManyField(to="store.Size", related_name="sizes") slug = models.SlugField(unique=True, allow_unicode=True, db_collation='utf8_persian_ci') price = models.PositiveIntegerField() description = models.TextField() inventory = models.IntegerField() datetime_created = models.DateTimeField(auto_now_add=True) datetime_modified = models.DateTimeField(auto_now=True) discounts = models.IntegerField(default=0) available_colors = models.ManyToManyField(to="store.Color", related_name="colors") status = models.BooleanField(default=True) def __str__(self): return self.name def get_absolute_url(self): return reverse("product_detail", kwargs={"slug": self.slug})class Size(models.Model): size = models.CharField(max_length=2) def __str__(self): return self.sizeclass Color(models.Model): color = ColorField() name = models.CharField(max_length=200) def __str__(self): return self.nameclass Picture(models.Model): picture = models.ImageField(upload_to=f'static/store/images/') product = models.ForeignKey(Product, default=None, related_name='images', on_delete=models.PROTECT) def __str__(self): return self.picture.urlviews:
def cart_detail_view(request): cart = Cart(request) colors = Color.objects.all() for item in cart: item['product_update_quantity_form'] = AddProductToCartForm(initial={'inplace': True, }) return render(request, 'products/cart_detail.html', {'cart': cart, 'colors': colors})def add_to_cart_view(request, pk): cart = Cart(request) product = get_object_or_404(Product, pk=pk) form = AddProductToCartForm(request.POST) print(request.POST) if form.is_valid(): cleaned_data = form.cleaned_data size = cleaned_data['size'] color = cleaned_data['color'] quantity = (cleaned_data['quantity']) replace_current_quantity = cleaned_data['inplace'] cart.add(product, size, color, quantity, replace_current_quantity) return redirect('cart_detail')def remove_item_from_cart(request, cart_item): cart = Cart(request) cart.remove(cart_item) return redirect('cart_detail')@require_POSTdef clear_cart(request): cart = Cart(request) if len(cart) != 0: cart.clear() return redirect('product_list')cart.py:
from .models import Productclass Cart: def __init__(self, request):""" Initialize the cart""" self.request = request self.session = request.session cart = self.session.get('cart') if not cart: cart = self.session['cart'] = {} self.cart = cart def add(self, product, size, color, quantity=1, replace_current_quantity=False):""" Add a product to the cart""" cart_item = '1' flag = True for item in self.cart.items(): if item[1]['product_id'] == product.id and item[1]['size'] == size and item[1]['color'] == color: if replace_current_quantity: item[1]['quantity'] = quantity else: item[1]['quantity'] += quantity flag = False keys = list(self.cart.keys()) if flag: while flag: if cart_item in keys: cart_item = str(int(cart_item) + 1) continue flag = False self.cart[cart_item] = {'product_id': product.id} self.cart[cart_item]['size'] = size self.cart[cart_item]['color'] = color self.cart[cart_item]['quantity'] = quantity self.save() def remove(self, cart_item): cart_item = str(cart_item)""" Remove a product from the cart""" if cart_item in self.cart.keys(): del self.cart[cart_item] self.save() def save(self):""" Mark session as modified to save changes""" self.session.modified = True def __iter__(self): product_ids = [value['product_id'] for value in self.cart.values()] products = Product.objects.filter(id__in=product_ids) cart = self.cart.copy() keys = list(cart.keys()) for index,product in enumerate(products): cart[str(keys[index])]['product_obj'] = product cart[str(keys[index])]['cart_item'] = keys[index] for item in cart.values(): item['total_price'] = item['product_obj'].price * item['quantity'] yield item def __len__(self): return len(self.cart) def clear(self): del self.session['cart'] self.save() def get_total_price(self): return sum(item['product_obj'].price * item['quantity'] for item in self.cart.values())urls:
from store import viewsurlpatterns = [ path('products/', views.ProductListView.as_view(), name='product_list'), path("products/<slug>/", views.ProductDetailView.as_view(), name='product_detail'), path("products/<slug>/comment", views.CommentView.as_view(), name='comment_create'), path('accounts/profile/', views.profile_view, name='account_profile'), path('cart/', views.cart_detail_view, name='cart_detail'), path('cart/add/<int:pk>/', views.add_to_cart_view, name="cart_add"), path('cart/remove/<int:cart_item>/', views.remove_item_from_cart, name='cart_remove'), path('clear/', views.clear_cart, name='cart_clear'),]forms:
class AddProductToCartForm(forms.Form): QUANTITY_CHOICES = [(i, str(i)) for i in range(1, 31)] quantity = forms.TypedChoiceField(choices=QUANTITY_CHOICES, coerce=int,) color = forms.CharField(max_length=20) size = forms.CharField(max_length=20) inplace = forms.BooleanField(required=False, widget=forms.HiddenInput)Traceback:
Environment:Request Method: GETRequest URL: http://127.0.0.1:8000/cart/Django Version: 5.0.1Python Version: 3.12.1Installed Applications:['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','allauth','allauth.account','allauth.socialaccount','allauth.socialaccount.providers.google','widget_tweaks','colorfield','store','core']Installed Middleware:['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.CommonMiddleware','django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware','allauth.account.middleware.AccountMiddleware']Traceback (most recent call last): File "D:\Django\shoe_store\venv\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner response = get_response(request) ^^^^^^^^^^^^^^^^^^^^^ File "D:\Django\shoe_store\venv\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\Django\shoe_store\store\views.py", line 67, in cart_detail_view for item in cart: ^^^^^^ File "D:\Django\shoe_store\store\cart.py", line 81, in __iter__ item['total_price'] = item['product_obj'].price * item['quantity'] ^^^^^^^^^^^^^^^^^^^Exception Type: KeyError at /cart/Exception Value: 'product_obj'i've tracked the process in debugger and found that it somehow traped in my Product model str method and finally this error raise.