Table Of Contents

Previous topic

Satchmo Views

Next topic

Google Base

Documentation Version:

Signals in Satchmo

Signals are a very powerful tool available in Django that allows you to decouple aspects of your application. The Django Signals Documentation, has this summary:

“In a nutshell, signals allow certain senders to notify a set of receivers that some action has taken place.”

In addition to all of the built in Django signals, Satchmo includes a number of store related signals. By using these signals, you can add very unique customizations to your store without needing to modify the Satchmo code.

Signal Descriptions

livesettings.signals.configuration_value_changed(sender, old_value=None, new_value=None, setting=None, **kwargs)

Base class for all signals

Internal attributes:

receivers
{ receriverkey (id) : weakref(receiver) }
satchmo_store.shop.signals.order_success(sender, order=None, **kwargs)

Sent when an order is complete and the balance goes to zero during a save.

Parameters:
  • sender (satchmo_store.shop.models.Order) – The order that was successful.
  • order (satchmo_store.shop.models.Order) – The order that was successful.

Note

order argument is the same as sender.

satchmo_store.shop.signals.order_cancel_query(sender, order=None, **kwargs)

Sent when an order is about to be cancelled and asks listeners if they allow to do so.

By default, orders in states ‘Shipped’, ‘Completed’ and ‘Cancelled’ are not allowed to be cancelled. The default verdict is stored in order.is_cancellable flag. Listeners can modify this flag, according to their needs.

Parameters:
  • sender (satchmo_store.shop.models.Order) – The order about to be cancelled.
  • order (satchmo_store.shop.models.Order) – The order about to be cancelled.

Note

order argument is the same as sender.

satchmo_store.shop.signals.order_cancelled(sender, order=None, **kwargs)

Sent when an order has been cancelled; it’s status already reflects it and has been saved to the database (e.g. payment gateway cancels payment).

Parameters:
  • sender (satchmo_store.shop.models.Order) – The order that was cancelled.
  • order (satchmo_store.shop.models.Order) – The order that was cancelled.

Note

order argument is the same as sender.

satchmo_store.shop.signals.satchmo_cart_add_complete(sender, cart=None, cartitem=None, product=None, request=None, form=None, **kwargs)

Sent after an item has been successfully added to the cart.

Parameters:
  • sender (satchmo_store.shop.models.Cart) – The cart the cart item was added to.
  • cart (satchmo_store.shop.models.Cart) – The cart the cart item was added to.
  • cartitem (satchmo_store.shop.models.CartItem) – The cart item that was added to the cart.
  • product (product.models.Product) – The product that was added to the cart.
  • form – The POST data for the form used to add the item to the cart.
  • request (django.http.HttpRequest) – The request that used in the view to add the item to the cart.

Note

cart is the same as sender.

satchmo_store.shop.signals.satchmo_cart_add_verify(sender, cart=None, cartitem=None, added_quantity=None, details=None, **kwargs)

Sent before an item is added to the cart.

Parameters:
  • sender (satchmo_store.shop.models.Cart) – The cart the cart item is being added to.
  • cart (satchmo_store.shop.models.Cart) – The cart the cart item is being added to.
  • cartitem (satchmo_store.shop.models.CartItem) – The cart item that is being added to the cart.
  • added_quantity (decimal.Decimal) – The number of satchmo_store.shop.models.CartItem instances items being added to the cart.
  • details

    A list of dictionaries containing additional details about the item if the item is a custom product or a gift certificate product. Each dictionary has the following entries:

    name:The name of the detail
    value:The value of the detail
    value:The value of the detail
    sort_order:The order the detail should be listed in displays
    price_change:The price change of the detail
    default:zero

Note

cart is the same as sender.

satchmo_store.shop.signals.satchmo_cart_changed(sender, cart=None, request=None, **kwargs)

Sent whenever the status of the cart has changed. For example, when an item is added, removed, or had it’s quantity updated.

Parameters:
  • sender (satchmo_store.shop.models.Cart) – The cart that was changed.
  • cart (satchmo_store.shop.models.Cart) – The cart that was changed.
  • request (django.http.HttpRequest) – The request that used in the view to add the item to the cart.

Note

cart is the same as sender.

satchmo_store.shop.signals.satchmo_cartitem_price_query(sender, cartitem=None, **kwargs)

Sent by the pricing system to allow price overrides when displaying line item prices.

Parameters:
  • sender (satchmo_store.shop.models.CartItem) – The cart item being queried for price overrides.
  • cartitem (satchmo_store.shop.models.CartItem) – The cart item being queried for price overrides.

Note

cartitem is the same as sender.

satchmo_store.shop.signals.satchmo_cart_details_query(sender, product=None, quantity=None, details=None, request=None, form=None, **kwargs)

Sent before an item is added to the cart so that listeners can update product details.

Parameters:
  • sender (satchmo_store.shop.models.Cart) – The cart the cart item is being added to.
  • product (product.models.Product or product.models.ConfigurableProduct) – The product that is being added to the cart.
  • quantity (decimal.Decimal) – The number of satchmo_store.shop.models.CartItem instances items being added to the cart.
  • details

    A list of dictionaries containing additional details about the item if the item is a custom product or a gift certificate product. Each dictionary has the following entries:

    name:The name of the detail
    value:The value of the detail
    value:The value of the detail
    sort_order:The order the detail should be listed in displays
    price_change:The price change of the detail
  • form – The POST data for the form used to add the item to the cart.
  • request (django.http.HttpRequest) – The request that used in the view to add the item to the cart.

Note

cart is the same as sender.

satchmo_store.shop.signals.satchmo_post_copy_item_to_order(sender, cartitem=None, order=None, orderitem=None, **kwargs)

Sent after each item from the cart is copied into an order.

Parameters:
  • sender (satchmo_store.shop.models.Cart) – The cart the cart items are being copied into.
  • cartitem (satchmo_store.shop.models.CartItem) – The cart item being copied into an order.
  • order (satchmo_store.shop.models.Order) – The order having items copied into it.
  • orderitem (satchmo_store.shop.models.OrderItem) – The order item being added to the order.
satchmo_store.shop.signals.satchmo_context(sender, context=None, **kwargs)

Sent when satchmo_store.shop.context_processors.settings() is invoked, before the context is returned. This signal can be used to modify the context returned by the context processor.

Parameters:
  • sender (satchmo_store.shop.models.Config) – The current store configuration
  • context

    A dictionary containing the context to be returned by the context processor. The dictionary contains:

    shop_base:The base URL for the store
    shop:An instance of satchmo_store.shop.models.Config representing the current store configuration
    shop_name:The shop name
    media_url:The current media url, taking into account SSL
    cart_count:The number of items in the cart
    cart:An instance of satchmo_store.shop.models.Cart representing the current cart
    categories:A QuerySet of all the product.models.Category objects for the current site.
    is_secure:A boolean representing weather or not SSL is enabled
    request:The HttpRequest object passed into the context processor
    login_url:The login url defined in settings.LOGIN_URL
    logout_url:The logout url defined in settings.LOGOUT_URL
    sale:An instance of product.models.Discount if there is a current sale, or None
satchmo_store.shop.signals.cart_add_view(sender, request=None, method=None, **kwargs)

Sent by ‘views.smart_add` to allow listeners to optionally change the responding function.

Parameters:
  • sender (satchmo_store.shop.models.Cart) – The cart model
  • request (django.http.HttpRequest) – The request used by the view
  • method

    A dictionary containing a single key view to be updated with the function to be called by smart_add. For example:

    method = {'view': cart.add }
    

Note

sender is not a class instance.

satchmo_store.shop.signals.sendfile_url_for_file(sender, file=None, product=None, url_dict={}, **kwargs)

Sent to determine where to redirect a user for a DownloadableProduct.

Parameters:
  • sender (None) – None
  • file (django.db.models.fields.files.FileField) – The 'file' field of the DownloadableProduct.
  • product (product.models.DownloadableProduct) – The product which is being downloaded.
  • url_dict – A dictionary containing a single entry, 'url', the URL which the user will be redirected to. Listeners should modify this value to change the redirect URL.

Warning

For a sane filename parameter in the Content-Disposition header, users are cautioned against appending a trailing slash('/') to the URL.

satchmo_store.shop.signals.rendering_store_mail(sender, send_mail_args={}, context={}, **kwargs)

Sent by satchmo_store.mail.send_store_mail() before the message body is rendered.

Takes the same arguments as sending_store_mail.

Note

send_mail_args does not contain the 'subject' entry.

Note

If the 'message' entry is set in send_mail_args by a listener, it will be used instead of the rendered result in send_store_mail().

satchmo_store.shop.signals.sending_store_mail(sender, send_mail_args={}, context={}, **kwargs)

Sent by satchmo_store.mail.send_store_mail() just before send_mail() is invoked.

Listeners may raise satchmo_store.mail.ShouldNotSendMail.

If they choose to invoke django.mail.EmailMessage.send(), any errors raised will be handled by send_store_mail(); they should consequently raise ShouldNotSendMail to avoid re-sending the email.

Parameters:
  • sender – Defaults to None, unless the sender argument to send_store_mail() is specified; see below.
Parameters:
  • send_mail_args

    A dictionary containing the keyword arguments passed to send_mail():

    • subject
    • message
    • from_email
    • recipient_list
    • fail_silently
  • context – The context used to render the message body; by default, it contains the ‘shop_name’ key, but may contain other keys, depending on the context argument to send_store_mail().
  • **kwargs – Additional keyword arguments received by send_store_mail().

Note

If the context argument to send_store_mail() contains the entry send_mail_args, it will not be available in the listener’s context dictionary.

Example:

from satchmo_store.shop.signals import order_notice_sender

def modify_subject(sender, send_mail_args={}, context={}, **kwargs):
  if not ('shop_name' in context and 'order' in context):
    return

  send_mail_args['subject'] = '[%s] Woohoo! You got a *new* order! (ID: #%d)' % \
      (context['shop_name'], context['order'].id)

sending_store_mail.connect(modify_subject, sender=order_notice_sender)
satchmo_store.contact.signals.satchmo_contact_view(sender, contact=None, contact_dict=None, **kwargs)

Sent when contact information is viewed or updated before a template is rendered. Allows you to override the contact information and context passed to the templates used.

Parameters:
  • sender (satchmo_store.contact.models.Contact) – The contact representing the contact information being viewed, or None if the information cannot be found.
  • contact (satchmo_store.contact.models.Contact) – The contact representing the contact information being viewed, or None if the information cannot be found.
  • contact_dict – A dictionary containing the intitial data for the instance of satchmo_store.contact.forms.ExtendedContactInfoForm instance that will be rendered to the user.

Note

contact is the same as sender.

satchmo_store.contact.signals.satchmo_contact_location_changed(sender, contact=None, **kwargs)

Sent after a user changes their location in their profile.

Parameters:
  • sender (satchmo_store.contact.forms.ContactInfoForm) – The form which was responsible for the location change.
  • contact (satchmo_store.contact.models.Contact) – The contact which was updated with a new location.
satchmo_store.contact.signals.validate_postcode(sender, postcode=None, country=None, **kwargs)

Sent when a form that contains postal codes (shipping and billing forms) needs to validate. This signal can be used to custom validate postal postal codes. Any listener should return the validated postal code or raise an exception for an invalid postal code.

Parameters:
  • sender (satchmo_store.contact.forms.ContactInfoForm) – The form which is validating its postal codes.
  • postcode – The postal code as a string being validated.
  • country (l10n.models.Country) – The country that was selected in the form (or specified in the configuration if local sales are only allowed).
satchmo_store.accounts.signals.satchmo_registration(sender, contact=None, subscribed=None, data=None, **kwargs)

Sent after a user has registered an account with the store.

Parameters:
  • sender (satchmo_store.accounts.forms.RegistrationForm) – The form which was submitted.
  • contact (satchmo_store.contact.models.Contact) – The contact that was saved to the database.
  • subscribed

    A boolean reflecting whether or not the user subscribed to a newsletter

    default:False
  • data – The cleaned_data dictionary of the submitted form.
satchmo_store.accounts.signals.satchmo_registration_verified(sender, contact=None, **kwargs)

Sent after a user account has been verified. This signal is also sent right after an account is created if account verification is disabled.

Parameters:
  • sender – An instance of satchmo_store.models.Contact if the account was verified via email (Note: this is the same argument as contact), or an instance of satchmo_store.accounts.forms.RegistrationForm if account verification is disabled.
  • contact (satchmo_store.models.Contact) – The contact that was registered.
satchmo_ext.newsletter.signals.newsletter_subscription_updated(sender, old_state=None, new_state=None, contact=None, attributes=None, **kwargs)

Sent after a newsletter subscription has been updated.

Parameters:
  • sender (satchmo_store.models.Contact) – The contact for which the subscription status is being updated.
  • old_state – A Boolean representing the old state of subscription.
  • new_state – A Boolean representing the new state of the subscription.
  • contact (satchmo_store.models.Contact) – The contact for which the subscription status is being updated.
  • attributes – An empty dictionary. This argument is not currently used.
payment.signals.confirm_sanity_check(sender, controller=None, **kwargs)

Sent after ensuring that the cart and order are valid.

Parameters:
  • sender (payment.views.confirm.ConfirmController) – The controller which performed the sanity check.
  • controller (payment.views.confirm.ConfirmController) – The controller which performed the sanity check.

Note

sender is the same as controller.

payment.signals.payment_methods_query(sender, methods=None, cart=None, order=None, contact=None, **kwargs)

Sent when a payment.forms.PaymentMethodForm is initialized. Receivers have cart/order passed in variables to check the contents and modify methods list if neccessary.

Parameters:
  • sender (payment.forms.PaymentMethodForm) – The form that is being initialized.
  • methods – A list of 2-element tuples containing the name and label for each active payment module.
  • cart (satchmo_store.shop.models.Cart) – The cart.
  • order (satchmo_store.shop.models.Order) – The current order.
  • contact (satchmo_store.contact.models.Contact) – The contact representing the current customer if authenticated; it is None otherwise.

The following example shows how to conditionally modify the payment choices presented to a customer:

def adjust_payment_choices(sender, contact, methods, **kwargs):
    if should_reduce: # whatever your condition is
        for method in methods:
            if method[0] == 'PAYMENT_PMTKEY':
                methods.remove(method)
payment.signals.payment_choices(sender, choices=None, **kwargs)

Sent after a list of payment choices is compiled, allows the editing of payment choices.

Parameters:
  • sender – Always None
  • methods – A list of 2-element tuples containing the name and label for each active payment module.
product.signals.index_prerender(sender, request=None, context=None, category=None, brand=None, object_list=None, **kwargs)

Sent before an index is rendered for categories or brands.

Parameters:
  • sender

    An instance of one of the following models:

    • product.models.product
    • satchmo_ext.brand.models.Brand
    • satchmo_ext.brand.models.BrandProduct
  • request (django.http.HttpRequest) – The request used by the view.
  • context – A dictionary containing the context that will be used to render the template. The contents of this dictionary changes depending on the sender.
  • category (product.models.Category) – The category being viewed.
  • brand (satchmo_ext.brand.modes.Brand) – The brand being viewed.
  • object_list – A QuerySet of product.models.Product objects.

Note

category and brand will not be passed for category listings.

product.signals.satchmo_price_query(sender, price=None, slug=None, discountable=None, **kwargs)

Sent before returning the price of a product.

Parameters:
  • sender

    An instance of one of the following models:

    • product.models.ProductPriceLookup
    • product.models.Price
    • satchmo_ext.tieredpricing.models.TieredPrice
  • price – The instance of the model sending the price query.
  • slug – The slug of the product being queried
  • discountable – A Boolean representing whether or not the product price is discountable

Note

slug and discountable are only sent by product.models.ProductPriceLookup.

Note

price is the same as sender

product.signals.subtype_order_success(sender, product=None, order=None, subtype=None, **kwargs)

Sent when a downloadable product is successful.

Parameters:
  • sender (product.models.DownloadableProduct) – The product that was successfully ordered.
  • product (product.models.DownoadableProduct) – The product that was successfully ordered.
  • order (satchmo_store.shop.models.Order) – The successful order for the product.
  • subtype – Always the string "download".
product.signals.discount_filter_items(sender, discounted=None, order=None, **kwargs)

Sent to verify the set of order items that are subject to discount.

Listeners should modify the “discounted” dictionary to change the set of discounted cart items.

Parameters:
  • sender (product.models.Discount) – The discount being applied.
  • discounted – A dictionary, where the keys are IDs of items which are subject to discount by standard criteria.
  • order (satchmo_store.shop.models.Order) – The order being processed.

External Signals Used in Satchmo

Satchmo depends on signals in signals_ahoy.signals and triggers them at various points of execution; below are some of them.

Sent by satchmo_store.shop.views.search.search_view() to ask all listeners to add search results.

Arguments sent with this signal:

sender
The product.models.Product model (Note: not an instance of Product)
request
The HttpRequest object used in the search view
category
The category slug to limit a search to a specific category
keywords
A list of keywords search for
results

A dictionary of results to update with search results. The contents of the dictionary should contain the following information:

categories
A QuerySet of product.models.Cateogry objects which matched the search criteria
products
A Queryset of product.models.Product objects which matched the search critera
signals_ahoy.signals.collect_urls()

Sent by urls modules to allow listeners to add or replace urls to that module

Arguments sent with this signal:

sender
The module having url patterns added to it
patterns
The url patterns to be added. This is an instance of django.conf.urls.defaults.patterns
section
The name of the section adding the urls (Note: this argument is not always provided). For example ‘__init__’ or ‘product’

Example:

from satchmo_store.shop.signals import satchmo_cart_add_complete
import myviews

satchmo_cart_add_complete.connect(myviews.cart_add_listener, sender=None)
signals_ahoy.signals.form_init()

Sent when a contact info form is initialized. Contact info forms include:

  • contact.forms.ContactInfoForm
  • contact.forms.ExtendedContactInfoForm
  • payment.forms.PaymentContactInfoForm

Arguments sent with this signal:

sender
The model of the form being initialized. The value of sender will be one of the models defined above.
form
An instance of the form (whose type is defined by sender) being intitialized.

See Ensuring Acceptance of Terms during Checkout for an example of how this signal can be used.

signals_ahoy.signals.form_postsave()

Sent after a form has been saved to the database

Arguments sent with this signal:

sender

The form model of the form being set (Note: Not an instance). Possible values include:

  • satchmo_store.contact.forms.ContactInfoForm
  • payment.modules.purchaseorder.forms.PurchaseorderPayShipForm
  • payment.forms.CreditPayShipForm
  • payment.forms.SimplePayShipForm
  • payment.forms.PaymentContactInfoForm
form
  • The instance of the form defined by one of the above models that was saved.
object
  • A satchmo_store.contact.models.Contact instance if the form being saved is an instance of satchmo_store.contact.forms.ContactInfoForm otherwise this value does not exist.
formdata
  • The data associated with the form if the form being saved is an instance of satchmo_store.contact.forms.ContactInfoForm otherwise this value does not exist.

Examples

Putting it All Together

This section contains a brief example of how to use signals in your application. For this example, we want to have certain products that are only available to members. Everyone can see the products, but only members can add to the cart. If a non-member tries to purchase a product, they will get a clear error message letting them know they need to be a member.

The first thing to do is create a listeners.py file in your app. In this case, the file would look something like this:

"""
A custom listener that will evaluate whether or not the product being added
to the cart is available to the current user based on their membership.
"""
from satchmo_store.shop.exceptions import CartAddProhibited
from django.utils.translation import gettext_lazy as _

class ContactCannotOrder(CartAddProhibited):
    def __init__(self, contact, product, msg):
        super(ContactCannotOrder, self).__init__(product, msg)
        self.contact = contact

def veto_for_non_members(sender, cartitem=None, added_quantity=0, **kwargs):
    from utils import can_user_buy
    customer = kwargs['cart'].customer
    if can_user_buy(cartitem.product, customer):
        return True
    else:
        msg = _("Only members are allowed to purchase this product.")
        raise ContactCannotOrder(customer, cartitem.product, msg)

Next, you need to create the can_user_buy function. Your utils.py file could look something like this (details left up to the reader):

def can_user_buy(product, contact=None):
    """
    Given a product and a user, return True if that person can buy it and
    False if they can not.
    This doesn't work as it stands now. You'll need to customize the
    is_member function
    """
    if is_member(contact):
        return True
    else:
        return False

The final step is to make sure your new listener is hooked up. In your models.py add the following code:

from listeners import veto_for_non_members
from satchmo_store.shop import signals

signals.satchmo_cart_add_verify.connect(veto_for_non_members, sender=None)

Now, you should be able to restrict certain products to only your members. The nice thing is that you’ve done this without modifying your satchmo base code.

Ensuring Acceptance of Terms during Checkout

The signal signals_ahoy.signals.form_init() can be combined with the payment.listeners.form_terms_listener to add a custom terms and conditions acceptance box into your checkout flow.

First, add the terms view in your /localsite/urls.py file:

urlpatterns += patterns('',
url(r'^shop_terms/$', 'project-name.localsite.views.shop_terms',
    name="shop_terms"),
)

Next, create the view in your /localsite/views.py to display the terms:

from django.shortcuts import render_to_response
from django.template import RequestContext

def shop_terms(request):
    ctx = RequestContext(request, {})
    return render_to_response('localsite/shop-terms.html',
        context_instance=ctx)

Now, you will need modify the checkout html to display the new form. Copy /satchmo/apps/payment/templates/shop/checkout/pay_ship.html to /project-name/templates/shop/checkout/pay_ship.html.

Add the following code to the copied pay_ship.html to display the form:

{{ form.terms }} {{ form.terms.label|safe }}
{% if form.terms.errors %}<br/>**{{ form.terms.errors|join:", " }}{% endif %}

Make sure you register the forms_terms_listener by adding the following code to your /localsite/models.py:

from payment.forms import SimplePayShipForm
from payment.listeners import form_terms_listener
from signals_ahoy.signals import form_init

form_init.connect(form_terms_listener, sender=SimplePayShipForm)

The final step is to create your actual store-name/templates/localsite/shop-terms.html, like this:

{% extends "base.html" %}
{% block content %}
<p>Put all of your sample terms here.</p>
{% endblock %}

Now, when users checkout, they must agree to your store’s terms.