session-cart / session_cart /

'''Session based shopping cart'''
from django.core.exceptions import ImproperlyConfigured
from .utils import import_cart

class CartItem(object):
    '''Lightweight container for cart items'''
    __slots__ = ('item', 'quantity',)
    def __init__(self, item, quantity=1):
        self.item = item
        self.quantity = quantity

    def __repr__(self):
        return 'CartItem(%r, %r)' % (self.item, self.quantity)

    def __cmp__(self, other):
        if isinstance(other, CartItem):
            return cmp(self.item, other.item)
        return cmp(self.item, other)

class Cart(list):
    '''Handles a list of items stored in the session'''
    model = None
    def __init__(self, request, name='cart'):
        super(Cart, self).__init__()
        self.request = request = name
        if self.model is None:
            from django.db import models
            from django.conf import settings
                Cart.model = import_cart(settings.CART_MODEL)
            except AttributeError:
                raise ImproperlyConfigured("%s isn't a valid Cart model." % settings.CART_MODEL)
        # Cart is stored as a list of ( item_id, quantity )
        for item, quantity in request.session.get(, []):
                self.append(item, quantity)
            except self.model.DoesNotExist:

    def save(self):
        '''Save this cart to the session'''
        self.request.session[] = tuple(
            (, i.quantity,)
            for i in self

    def _get(self, item):
        '''Ensure item is an instance of self.model'''
        if not isinstance(item, self.model):
            return self.model._default_manager.get(pk=item)
        return item

    def append(self, item, quantity =1):
        item = self._get(item)
            self[self.index(item)].quantity += quantity
        except ValueError:
            super(Cart, self).append(CartItem(item, quantity))

    def index(self, value, **kwargs):
        '''Prevent duplication of (item, quantity) pairs.'''
        if isinstance(value, self.model):
            value = CartItem(value)
        return super(Cart, self).index(value)

    def remove(self, item):
        super(Cart, self).remove(self._get(item))

    def empty(self):
        '''Remove all items from cart'''
        while len(self):

    def __repr__( self ):
        return ','.join([repr(x) for x in self])