Управление корзиной для незарегистрированных пользователей с сессиями на Django - PullRequest
0 голосов
/ 27 октября 2019

Я хочу, чтобы пользователи могли добавлять товары в корзину и оформлять покупки без регистрации. Я пытаюсь связать session_key с каждой корзиной, чтобы упорядочить вещи. Однако я не уверен насчет некоторых вещей:

  1. Как добавить мой session_key в качестве поля для моей модели
  2. Как распознать, когда создать новый сеанс

Вот мой код для моей корзины / models.py

from django.conf import settings
from django.db import models
from django.db.models.signals import pre_save, post_save, m2m_changed
from django.contrib.sessions.models import Session

from paintings.models import Painting

# https://stackoverflow.com/questions/29113548/django-anonymous-session-temporary-one-to-one-related-model


class CartManager(models.Manager):

    def new_or_get(self, request):
    #getting existing object if it exists, create new object if none exists

        cart_id = request.session.get("cart_id", None) #get the current id or None

        qs = self.get_queryset().filter(id=cart_id)
        #querying the id to make sure that it actually exist
        if qs.count() == 1:
            new_obj = False
            cart_obj = qs.first()

        #if the id doesn't exist then we'll create a brand new one and start that new session
        else:
            cart_obj = Cart.objects.new_cart(user=request.user)
            new_obj = True
            request.session['cart_id'] = cart_obj.id #this is the setter    

        return cart_obj, new_obj

    def new_cart(self, user=None):
        print(user)
        user_obj = None
        if user is not None:
            if user.is_authenticated:
                user_obj = user
                defaults = {'session_key': request.session.session_key}
            else:
                session_key = request.session.session_key,
                defaults = {'user': None}
        return self.model.objects.create(user=user_obj)


class Cart(models.Model):
    products        = models.ManyToManyField(Painting, blank=True) #blank=True because we want the ability to have an empty cart
    sub_total       = models.DecimalField(default=0.00, max_digits=100, decimal_places=2) 
    shipping        = models.DecimalField(default=0.00, max_digits=100, decimal_places=2)     
    total           = models.DecimalField(default=0.00, max_digits=100, decimal_places=2)
    updated         = models.DateTimeField(auto_now=True) #to track when the cart was updated    
    timestamp       = models.DateTimeField(auto_now_add=True) #to track when the painting was added to the cart
    session_key     = models.CharField(max_length=40, null=True)

    objects = CartManager()

    def __str__(self):
        return str(self.id)


#whenever I hit save this is called
def m2m_changed_cart_receiver(sender, instance, action, *args, **kwargs):

        #see here for explaination of actions: https://docs.djangoproject.com/en/2.2/ref/signals/#m2m-changed
        if action == 'post_add' or action == 'post_remove' or action == 'post_clear': 

            #getting all the paintings
            products = instance.products.all()
            total = 0

            #adding each painting to get the total price
            for x in products:
                total += x.price
            if instance.sub_total != total:
                instance.sub_total = total
                instance.save()

#m2m_changed documentation: https://docs.djangoproject.com/en/2.2/ref/signals/#m2m-changed
m2m_changed.connect(m2m_changed_cart_receiver, sender=Cart.products.through) #we need the through method for the m2m

#django manytomany documentation:
#https://docs.djangoproject.com/en/2.2/topics/db/examples/many_to_many/

def pre_save_cart_receiver(sender, instance, *args, **kwargs):

    #only add the tax, shipping etc if sub_total is > 0. (replace +10 with actual tax/ shipping later)
    if instance.sub_total > 0:
        instance.total = float(instance.sub_total) * 1 #instead of +10, play around to get the taxes and shipping rates later
    else:
        instance.total = 0.00

pre_save.connect(pre_save_cart_receiver, sender=Cart)

Вот мой views.py (это представление для моей Django Rest Framework)

from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.response import Response
from rest_framework import generics, permissions, pagination, status

from .models import Cart
from .permissions import IsOwnerOrReadOnly
from .serializers import CartSerializer


class CartListCreateAPIView(generics.ListCreateAPIView):
    queryset            = Cart.objects.all()
    serializer_class    = CartSerializer
    permission_classes  = [permissions.AllowAny]    
    # permissions.AllowAny allows POST for users that are not logged in
    # https://www.django-rest-framework.org/api-guide/permissions/#setting-the-permission-policy


    def perform_create(self, serializer):
        serializer.save()

    def get_queryset(self):
        # filter the queryset based on the filters applied
        queryList = Cart.objects.all()

        return queryList

Я не уверен, что это лучший способ сделать это.

Большое спасибо заранее!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...