easycart.cart

Core classes to represent the user cart and items in it.

BaseCart

class easycart.cart.BaseCart(request)[source]

Base class representing the user cart.

In the simplest case, you just subclass it in your views and override the get_queryset() method.

If multi-table inheritance is used to store information about items, then you may also want to override process_object() as well.

Parameters:

request (django.http.HttpRequest)

Variables:
  • items (dict) – A map between item primary keys (converted to strings) and corresponding instances of item_class. If, for some reason, you need to modify items directly, don’t forget to call update() afterwards.
  • item_count (int) – The total number of items in the cart. By default, only unique items are counted.
  • total_price (same as the type of item prices) – The total value of all items in the cart.
  • request – A reference to the request used to instantiate the cart.
item_class

Class to use to represent cart items.

alias of BaseItem

add(pk, quantity=1, **kwargs)[source]

Add an item to the cart.

If the item is already in the cart, then its quantity will be increased by quantity units.

Parameters:
  • pk (str or int) – The primary key of the item.
  • quantity (int-convertible) – A number of units of to add.
  • **kwargs – Extra keyword arguments to pass to the item class constructor.
Raises:
change_quantity(pk, quantity)[source]

Change the quantity of an item.

Parameters:
  • pk (str or int) – The primary key of the item.
  • quantity (int-convertible) – A new quantity.
Raises:
remove(pk)[source]

Remove an item from the cart.

Parameters:pk (str or int) – The primary key of the item.
Raises:ItemNotInCart
empty()[source]

Remove all items from the cart.

list_items(sort_key=None, reverse=False)[source]

Return a list of cart items.

Parameters:
  • sort_key (func) – A function to customize the list order, same as the ‘key’ argument to the built-in sorted().
  • reverse (bool) – If set to True, the sort order will be reversed.
Returns:

list – List of item_class instances.

Examples

>>> cart = Cart(request)
>>> cart.list_items(lambda item: item.obj.name)
[<CartItem: obj=bar, quantity=3>,
 <CartItem: obj=foo, quantity=1>,
 <CartItem: obj=nox, quantity=5>]
>>> cart.list_items(lambda item: item.quantity, reverse=True)
[<CartItem: obj=nox, quantity=5>,
 <CartItem: obj=bar, quantity=3>,
 <CartItem: obj=foo, quantity=1>]
encode(formatter=None)[source]

Return a representation of the cart as a JSON-response.

Parameters:formatter (func, optional) – A function that accepts the cart representation and returns its formatted version.
Returns:django.http.JsonResponse

Examples

Assume that items with primary keys “1” and “4” are already in the cart.

>>> cart = Cart(request)
>>> def format_total_price(cart_repr):
...     return intcomma(cart_repr['totalPrice'])
...
>>> json_response = cart.encode(format_total_price)
>>> json_response.content
b'{
    "items": {
        '1': {"price": 100, "quantity": 10, "total": 1000},
        '4': {"price": 50, "quantity": 20, "total": 1000},
    },
    "itemCount": 2,
    "totalPrice": "2,000",
}'
get_queryset(pks)[source]

Construct a queryset using given primary keys.

The cart is pretty much useless until this method is overriden. The default implementation just raises NotImplementedError.

Parameters:pks (list of str)
Returns:django.db.models.query.QuerySet

Examples

In the most basic case this method may look like the one below:

def get_queryset(self, pks):
    return Item.objects.filter(pk__in=pks)
process_object(obj)[source]

Process an object before it will be used to create a cart item.

This method provides a hook to perform arbitrary actions on the item’s model instance, before it gets associated with the cart item. However, it’s usually used just to replace the passed model instance with its related object. The default implementation simply returns the passed object.

Parameters:obj (item model) – An item’s model instance.
Returns:item model – A model instance that will be used as the obj argument to item_class.
handle_stale_items(pks)[source]

Handle cart items that are no longer present in the database.

The default implementation results in silent removal of stale items from the cart.

Parameters:pks (set of str) – Primary keys of stale items.
create_items(session_items)[source]

Instantiate cart items from session data.

The value returned by this method is used to populate the cart’s items attribute.

Parameters:session_items (dict) – A dictionary of pk-quantity mappings (each pk is a string). For example: {'1': 5, '3': 2}.
Returns:dict – A map between the session_items keys and instances of item_class. For example:
{'1': <CartItem: obj=foo, quantity=5>,
 '3': <CartItem: obj=bar, quantity=2>}
update()[source]

Update the cart.

First this method updates attributes dependent on the cart’s items, such as total_price or item_count. After that, it saves the new cart state to the session.

Generally, you’ll need to call this method by yourself, only when implementing new methods that directly change the items attribute.

count_items(unique=True)[source]

Count items in the cart.

Parameters:unique (bool-convertible, optional)
Returns:int – If unique is truthy, then the result is the number of items in the cart. Otherwise, it’s the sum of all item quantities.
count_total_price()[source]

Get the total price of all items in the cart.

BaseItem

class easycart.cart.BaseItem(obj, quantity=1, **kwargs)[source]

Base class representing the cart item.

Parameters:
  • obj (subclass of django.db.models.Model) – A model instance holding database information about the item. The instance is required to have an attribute containing the item’s price.
  • quantity (int, optional) – A quantity to associate with the item.
Variables:
  • obj – A reference to the obj argument.
  • price (same as obj.price) – The price of the item (a reference to the corresponding attribute on the obj).
Raises:
cart = None

A reference to the instance of the cart class holding the item.

PRICE_ATTR = 'price'

str – The name of the obj attribute containing the item’s price.

max_quantity = None

The maximum quantity allowed per item.

Used by the clean_quantity() method. Should be either a positive integer or a falsy value. The latter case disables the check. Note that you can make it a property to provide dynamic values.

Examples

If you want to ensure that the user can’t put more items in his cart than you have in stock, you may write something like this:

class CartItem(BaseItem):
    @property
    def max_quantity(self):
        return self.obj.stock
quantity

int – The quantity associated with the item.

A read/write property.

New values are checked and normalized to integers by the clean_quantity() method.

total

same as obj.price – Total price of the item.

A read-only property.

The default implementation simply returns the product of the item’s price and quantity. Override to adjust for things like an individual item discount or taxes.

clean_quantity(quantity)[source]

Check and normalize the quantity.

The following checks are performed:

  • the quantity can be converted to an integer
  • it’s positive
  • it’s doesn’t exceed the value of max_quantity
Parameters:

quantity (int-convertible)

Returns:

int – The normalized quanity.

Raises:

Exceptions

class easycart.cart.CartException(**kwargs)[source]

Bases: Exception

Base class for cart exceptions.

class easycart.cart.InvalidItemQuantity(**kwargs)[source]

Bases: easycart.cart.CartException

Base class for exceptions related to invalid item quantity.

class easycart.cart.ItemNotInCart(**kwargs)[source]

Bases: easycart.cart.CartException

Item with the given pk is not in the cart.

class easycart.cart.ItemNotInDatabase(**kwargs)[source]

Bases: easycart.cart.CartException

Database doesn’t contain an item with the given primary key.

class easycart.cart.NegativeItemQuantity(**kwargs)[source]

Bases: easycart.cart.InvalidItemQuantity

Provided item quantity is negative.

class easycart.cart.NonConvertibleItemQuantity(**kwargs)[source]

Bases: easycart.cart.InvalidItemQuantity

Provided item quantity can’t be converted to an integer.

class easycart.cart.TooLargeItemQuantity(**kwargs)[source]

Bases: easycart.cart.InvalidItemQuantity

Provided item quantity exceeds allowed limit.

class easycart.cart.ZeroItemQuantity(**kwargs)[source]

Bases: easycart.cart.InvalidItemQuantity

Provided item quantity is zero.