R
R
recursy2022-04-18 20:44:43
Django
recursy, 2022-04-18 20:44:43

Which is better to use in django receiver or sessions?

I am creating a shopping cart for an online store and I have a choice of how to implement this shopping cart. I don’t just need to screw it up for it to work, but it’s right, because I want to put the project on my resume.

1st way is to use databases, but receivers are used in this approach, I have heard a lot that this is bad form and it is better to never use them (receivers) at all.

class Product(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=64, unique=True)
    description = models.TextField(default='')
    cost = models.DecimalField(default=0.00, max_digits=10, decimal_places=2)


class Cart(models.Model):
    user = models.ForeignKey(User, null=True, blank=True, on_delete='CASCADE')
    count = models.PositiveIntegerField(default=0)
    total = models.DecimalField(default=0.00, max_digits=10, decimal_places=2)
    updated = models.DateTimeField(auto_now=True)
    timestamp = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return "User: {} has {} items in their cart. Their total is ${}".format(self.user, self.count, self.total)


class Entry(models.Model):
    product = models.ForeignKey(Product, null=True, on_delete='CASCADE')
    cart = models.ForeignKey(Cart, null=True, on_delete='CASCADE')
    quantity = models.PositiveIntegerField()

    def __str__(self):
        return "This entry contains {} {}(s).".format(self.quantity, self.product.name)


@receiver(post_save, sender=Entry)
def update_cart(sender, instance, **kwargs):
    line_cost = instance.quantity * instance.product.cost
    instance.cart.total += line_cost
    instance.cart.count += instance.quantity
    instance.cart.updated = datetime.now()


The 2nd way is to use django-sessions to store information about the user's products in sessions, the minus of this approach is that sessions live for 2 weeks, and after that the cart will be empty, which is also not very desirable.
from decimal import Decimal
from django.conf import settings
from shop.models import Product


class Cart(object):

    def __init__(self, request):
        """
        Инициализируем корзину
        """
        self.session = request.session
        cart = self.session.get(settings.CART_SESSION_ID)
        if not cart:
            # save an empty cart in the session
            cart = self.session[settings.CART_SESSION_ID] = {}
        self.cart = cart

def add(self, product, quantity=1, update_quantity=False):
    """
    Добавить продукт в корзину или обновить его количество.
    """
    product_id = str(product.id)
    if product_id not in self.cart:
        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

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Alexander Nesterov, 2022-04-18
@recursy

If you don't want to use signals, override the save method.
Well, no one bothers to use both solutions - sessions for anonymous users, a model for authorized ones.

D
Dr. Bacon, 2022-04-18
@bacon

You can always change the session lifetime, but the session is still tied to a specific browser, another computer, browser and that's it. And so, both options exist, there are already questions about business requirements

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question