Custom Product Modules

Though Satchmo includes a number of versatile product types, many projects have needs that are best met by creating a custom product module. A custom product module is a module with a product model which deviates from the normal behavior of Satchmo.

To work with custom product modules, you will need a basic understanding of Django apps, projects, and templates. You should understand the default behavior of Satchmo before trying to customize it.

Building your module

In a custom product module, most of the work is done in the models.py and template files. You will also need an admin.py file like for any other model which shall be available in the admin. This section contains several example files that you can add to a new or existing app and extend.

A basic models.py file with a custom product model looks like this:

from django.db import models
from django.utils.translation import ugettext_lazy as _
from product.models import Product

SATCHMO_PRODUCT=True

def get_product_types():
    """
    Returns a tuple of all product subtypes this app adds
    """
    return ('MyNewProduct', )

class MyNewProduct(models.Model):
    product = models.OneToOneField(Product, verbose_name=_('Product'),
        primary_key=True)

    def _get_subtype(self):
        """
        Has to return the name of the product subtype
        """
        return 'MyNewProduct'

    def __unicode__(self):
        return u"MyNewProduct: %s" % self.product.name

    class Meta:
        verbose_name = _('My New Product')
        verbose_name_plural = _('My New Products')

The important parts are the attribute MyNewProduct.product which links to the related product.models.Product and the method MyNewProduct._get_subtype() which returns a string representation of this model.

The function get_product_types() returns a list of all custom product models this app adds. This method is used to discover the custom product models from all installed apps.

This is the corresponding admin.py file. This file is needed to make your models visible in Django’s admin app:

from django.contrib import admin
from models import MyNewProduct

admin.site.register(MyNewProduct)

Configuration

Once you’ve created the above files in your app, you have all the code necessary to use your new product model in Satchmo. All that’s left is the configuration.

  1. Make sure that the app with your product model is in your project’s INSTALLED_APPS setting.
  2. Run python manage.py syncdb in your project directory.

You can now use the new product model in the same way that you would use one of Satchmo’s default product types. You will find an “Add MyNewProduct” link in the “Product Subtypes” section of each product’s admin page.

Extending the model and templates

A product model is a Django model with a OneToOneField to satchmo.product.models.Product and a _get_subtype method. You may add new fields and behavior as you would with any other Django model.

When Satchmo renders a product page, it looks for a template named product/detail_productname.html (in all lowercase). If the template is not found, Satchmo uses the base_product.html template.

As an example, say you are using MyNewProduct from the previous example and you want to extend it to display a special title on the product’s page. First, you would add a CharField named title to the existing model and to the table in your database (or just drop the table and run syncdb). Then, create a template named product/detail_mynewproduct.html with the following content:

{% extends "product/product.html" %}

{% block title %}{{ product.mynewproduct.title }}{% endblock title %}

If you create a MyNewProduct and view its page in the store, the page will have the title you assigned it in the admin app. Notice that the MyNewProduct is accessed as an attribute of product.

For more examples, look at product/models.py, templates/base_product.html, and templates/product/ in the Satchmo source code.

Using model inheritance

There is another possibility for extending the product model using model inheritance. You can find more information in the first installment of the Satchmo Diaries.

Warning

Using inheritance is currently not recommended, because it has some issues when it is used without care. Some methods of product.models.Product currently do not expect to find subtypes which inherit attributes and methods from product.models.Product.

If you want to use inheritance, make sure not to add your model to the list returned by get_product_types(), else you might get some trouble with infinite recursions. An alternative would be to extend the current implementation to be able to handle models which inherit from product.models.Product.

So, your models.py file should look like this:

from django.db import models
from django.utils.translation import ugettext_lazy as _
from product.models import Product

class MyNewProduct(Product):

    # TODO: your attributes here

    objects = ProductManager()

    def __unicode__(self):
        return u"MyNewProduct: %s" % self.name

    class Meta:
        verbose_name = _('My New Product')
        verbose_name_plural = _('My New Products')

To make this model available in the admin interface you should create a corresponding admin.py:

from django.contrib import admin
from models import MyNewProduct
from product.admin import ProductOptions

# TODO: do your customizations here
class MyNewProductAdmin(ProductOptions):
    pass

admin.site.register(MyNewProduct, MyNewProductAdmin)

Conclusion

This document should get you started in customizing Satchmo through the product model. If you need help with something discussed here or with more advanced topics, feel free to ask the mailing list.

Finally, if you create a product model that others may find useful, please consider contributing it to the Satchmo community.