2. How to create a Cart modifier¶
Cart modifiers are simple plugins that allow you to define rules according to which carts should be modified (and in what order).
Generally, this is how you implement a “bulk rebate” module, for instance.
2.1. Writing a simple cart modifier for the whole cart¶
Let’s assume you want to provide a discount of 10% off the cart’s total to clients that buy more than 500$ of goods.
This will affect the price of the whole cart. We will therefore override the
get_extra_cart_price_field()
method of
shop.cart.cart_modifiers_base.BaseCartModifier
:
from shop.cart.cart_modifiers_base import BaseCartModifier
from decimal import Decimal # We need this because python's float are confusing
class MyModifier(BaseCartModifier):
"""
An example class that will grant a 10% discount to shoppers who buy
more than 500 worth of goods.
"""
def get_extra_cart_price_field(self, cart, request):
ten_percent = Decimal('10') / Decimal('100')
# Now we need the current cart total. It's not just the subtotal field
# because there may be other modifiers before this one
total = cart.current_total
if total > Decimal('500'):
rebate_amount = total * ten_percent
rebate_amount = - rebate_amount # a rebate is a negative difference
extra_dict = { 'Rebate': '%s %%' % ten_percent }
return ('My awesome rebate', rebate_amount)
else:
return None # None is no-op: it means "do nothing"
def get_extra_cart_item_price_field(self, cart, request):
# Do modifications per cart item here
label = 'a label' # to distinguish, which modifier changed the price
extra_price = Decimal(0) # calculate addition cost here, can be a negative value
extra_dict = {} # an optional Python dictionary serializable as JSON
# which can be used to store arbitrary data
return (label, extra_price, extra_dict)
Adding this cart modifier to your SHOP_CART_MODIFIERS setting will enable it, and you should be able to already test that your cart displays a rebate when the total for the order is over 500.
Note
When using cart.extra_price_fields.append('your label', price)
you might
want to use from django.utils.translation import ugettext as _
for your
label in multilingual projects. Please make sure that you use gettext
The request object is passed into the methods get_extra_cart_price_field
and get_extra_cart_item_price_field
. This object contains the additional
temporary attribute cart_modifier_state
. This is an empty Python dictionary,
which can be used to pass arbitrary data from one cart modifier to another one.