Answer the question
In order to leave comments, you need to log in
How to properly display products on the shopping cart page?
I am learning Django. How to correctly display products from different categories on the shopping cart page if there are products with the same ID in different categories? For example, in the category "laptops" there is a product with id=5, and in the category "phones" there is a product with id=5. So, when adding a product to the cart and passing variables to the template, the page displays not only the product that was added to the cart, but also the product from another category with the same id.
Question: how to display laptops on the page if there are only laptops in the basket, phones, if there are only phones in the basket and all together.
Models
from django.db import models
from django.urls import reverse
class Note_Manufacturer(models.Model):
name = models.CharField(verbose_name='Производитель', max_length=50,
blank=True, null=True)
country = models.CharField(verbose_name='Страна', max_length=50,
blank=True, null=True)
def __str__(self):
return (str(self.name))
def note_manufacturer(self):
return reverse('note_manufacturer_detail', args=[str(self.pk)])
class Notebook(models.Model):
brand = models.ForeignKey(Note_Manufacturer, verbose_name='Производитель',
related_name='notebook_list',
max_length=20,
on_delete=models.CASCADE, null=True)
name = models.CharField(verbose_name='Модель', max_length=50,
blank=True, null=True, unique=True)
color = models.CharField(verbose_name='Цвет', max_length=50,
blank=True, null=True)
style = models.CharField(verbose_name='Категория', max_length=50,
blank=True, null=True)
price = models.DecimalField(verbose_name='Цена', max_digits=10,
decimal_places=2, null=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('note_product_detail', args=[str(self.pk)])
class Phone_Manufacturer(models.Model):
name = models.CharField(verbose_name='Производитель', max_length=50,
blank=True, null=True)
country = models.CharField(verbose_name='Страна', max_length=50,
blank=True, null=True)
def __str__(self):
return (str(self.name))
def phone_manufacturer(self):
return reverse('phone_manufacturer_detail', args=[str(self.pk)])
class Phone(models.Model):
brand = models.ForeignKey(Phone_Manufacturer, verbose_name='Производитель',
related_name='phone_list',
max_length=20,
on_delete=models.CASCADE, null=True)
name = models.CharField(verbose_name='Модель', max_length=50,
blank=True, null=True, unique=True)
color = models.CharField(verbose_name='Цвет', max_length=50,
blank=True, null=True)
style = models.CharField(verbose_name='Категория', max_length=50,
blank=True, null=True)
price = models.DecimalField(verbose_name='Цена', max_digits=10,
decimal_places=2, null=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('phone_product_detail', args=[str(self.pk)])
from django.shortcuts import render, redirect, get_object_or_404
from .cart import Cart
from .forms import CartAddForm
from my_first_site.note.models import Notebook
from my_first_site.phone.models import Phone
from orders.models import OrderItem
import itertools
def cart_detail(request):
cart = Cart(request)
for item in cart:
item['update_quantity_form'] = CartAddForm(
initial={'quantity': item['quantity'], 'update': True})
return render(request, 'cart_detail.html',
{
'cart': cart,
})
from decimal import Decimal
from django.conf import settings
from my_first_site.note.models import Notebook
from my_first_site.phone.models import Phone
class Cart(object):
def __init__(self, request):
# получаем объект сессии
self.session = request.session
# определяем сессию и называем ее cart
cart = self.session.get(settings.CART_SESSION_ID)
if not cart:
# сохраняем корзину в сессию
cart = self.session[settings.CART_SESSION_ID] = {}
self.cart = cart
def add(self, product, quantity=1, update_quantity=False):
# преобразуем id товара в строку чтобы использовать JSON
product_id = str(product.id)
if product_id not in self.cart:
# если товара нет в корзине,
# создаем словарь с количеством товаров - 0, и ценой преобразованной в строку
self.cart[product_id] = {
'quantity': 0, 'price': str(product.price)}
# обновляем количество товара в корзине
if update_quantity:
self.cart[product_id]['quantity'] = quantity
else:
# увеличиваем кол-во товаров в корзине
self.cart[product_id]['quantity'] += quantity
self.save()
def save(self):
# обновление сессии cart
self.session[settings.CART_SESSION_ID] = self.cart
# указываем что сессия изменена
self.session.modified = True
def remove(self, product):
# получаем id товара
product_id = str(product.id)
if product_id in self.cart:
self.cart[product_id]['quantity'] -= 1
if self.cart[product_id]['quantity'] <= 1:
# если товар в корзине, то удалить
del self.cart[product_id]
self.save()
def __iter__(self):
# перебор элементов корзины и получение их из базы данных
product_ids = self.cart.keys()
# получение объекта товара и добавление его в корзину
notes = Notebook.objects.filter(id__in=product_ids)
phones = Phone.objects.filter(id__in=product_ids)
for note in notes:
self.cart[str(note.id)]['note'] = note
for phone in phones:
self.cart[str(phone.id)]['phone'] = phone
for item in self.cart.values():
item['price'] = Decimal(item['price'])
item['total_price'] = item['price'] * item['quantity']
yield item
def __len__(self):
# подсчет всех товаров в корзине
return sum(item['quantity'] for item in self.cart.values())
def get_total_price(self):
# подсчет стоимости товаров в корзине
return sum(Decimal(
item['price']) * item['quantity']
for item in self.cart.values())
def clear(self):
del self.session[settings.CART_SESSION_ID]
self.session.modified = True
{% extends 'index.html' %}
{% load crispy_forms_tags %}
{% load static %}
{% block title %}
<title>Корзина</title>
{% endblock %}
{% block content%}
<h2>Корзина</h2>
{% if user.is_authenticated %}
<h2><a href="{% url 'order_create' %}">Оформить заказ</a></h2>
<div class="cart_products">
{% if cart|length > 0 %}
{% for item in cart %}
<div class="cart_product_item">
{% if item.note.pk %}
<div class="item_name">
<h3>Товар: {{ item.note.brand }} {{ item.note.name }}</h3>
</div>
<div class="item_body">
<p>
Идентификатор: {{ item.note.pk }}
</p>
<p>
Цена: {{ item.note.price }}
</p>
<p>
Количество: {{ item.quantity }} | Сумма: {{ item.total_price }}
</p>
<p><a href="{{ item.note.get_absolute_url }}">Описание товара</a></p>
</div>
<div class="add">
<form action="{% url 'cart_add_note' item.note.pk %}" method="POST">
{{ item.update_quantity_form.quantity }}
{{ item.update_quantity_form.update }}
{% csrf_token %}
<hr>
<input type="submit" value="Добавить в корзину" class="btn btn-primary btn-block">
<a href="{% url 'cart_remove_note' item.note.pk %}" class="btn btn-primary btn-block">Удалить из
корзины</a>
</form>
</div>
{% endif %}
{% if item.phone.pk %}
<div class="item_name">
<h3>Товар: {{ item.phone.brand }} {{ item.phone.name }}</h3>
</div>
<div class="item_body">
<p>
Идентификатор: {{ item.phone.pk }}
</p>
<p>
Цена: {{ item.phone.price }}
</p>
<p>
Количество: {{ item.quantity }} | Сумма: {{ item.total_price }}
</p>
<!-- phone - это модель товара Notebook, у нее вызываем метод get_absolute_url -->
<p><a href="{{ item.phone.get_absolute_url }}">Описание товара</a></p>
</div>
<div class="add">
<form action="{% url 'cart_add_phone' item.phone.pk %}" method="POST">
{{ item.update_quantity_form.quantity }}
{{ item.update_quantity_form.update }}
{% csrf_token %}
<hr>
<input type="submit" value="Добавить в корзину" class="btn btn-primary btn-block">
<a href="{% url 'cart_remove_phone' item.phone.pk %}" class="btn btn-primary btn-block">Удалить из
корзины</a>
</form>
</div>
{% endif %}
</div>
{% endfor %}
</div>
{% else %}
<p>Корзина пуста</p>
{% endif %}
{% endif %}
{% endblock %}
Answer the question
In order to leave comments, you need to log in
The schema is wrong. A phone and a laptop are one and the same entity, a commodity.
Let's say you put a laptop=5 in the cart, and then a phone=5. But there will be only one entry in the dictionary Cart.cart
, because the keys are the same. This is a mistake once.
And now look at what you will have in the variables if you perform the substitution:
def __iter__(self):
# перебор элементов корзины и получение их из базы данных
product_ids = self.cart.keys() # [5]
# получение объекта товара и добавление его в корзину
notes = Notebook.objects.filter(id__in=product_ids) # Notebook.objects.filter(id__in=[5])
phones = Phone.objects.filter(id__in=product_ids) # Phone.objects.filter(id__in=[5])
id == 5
product_id = f'{product._meta.app_label}.{product._meta.object_name}.{product.pk}'
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question