ProductsΒΆ

Handling a large number of different products can be a headache, since most products have very different properties from one another (think amazon and the plethora of differnet stuff they sell).

A core product model should be extensible to the shop needs. Different ways may exist for differnt use-cases:

  • Use model inheritance:

    class MySpecialProduct(Product):
        """
        Adds special attributes etc.
        """
    

    This would mean that a product is e.g. a DVD or a Vegetable, but never both. Although on database level this would be perfectly possible.

  • Use a kind of attachment approach:

    class MySpecialProductExtension(models.Model):
        """
        Adds special attributes and contains a relation to
        the core Product.
        """
    
        product = models.ForeignKey(Product)
    

    This way a product could get multiple different attachments to it. On database level this will be the same as using model inheritance. On python code level this has a different meaning (I think).

  • Use the attributes approach for user-added custom attributes. See snippets/products.py for this approach.

The core Product model should not need to know anything about these extensions. Django ORM will take care of reverse accessors to these extensions.

Other Django-based webshops handle the complexity in a clever way: make the core product very extensible with so-called product attributes. Similar to key-value tags, product attributes allow for very flexible product creation, and a clever set of model managers hide the complexity of theses added tables quite well.

Are there reasons why these attributes should relate to Product instead of implementing a generic attribute app? Maybe this way:

class Attribute(models.Model):
    # relation stuff
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

    # content and type
    value = models.CharField(max_length = 500)
    description = models.TextField()
    type = models.ForeignKey(AttributeType)

See snippets/products.py for more info.

This Page