Categorizing products

So far we've built a simple product model and simple catalog model. These models are excellent building blocks on which to begin adding new, more sophisticated functionality. As it stands, our catalog model design is unconnected to our products. We could add, as mentioned earlier, a ForeignKey from Product to Catalog. But this would allow for little in the way of organizing within the catalog, other than what we can do with the basic filter(), order_by(), and other ORM methods that Django provides.

Product categories are an extremely common solution to organization problems in web-based stores. Almost all major Internet retailers organize their products this way. It helps them to provide a more structured interface for their users and can give search engine indexers more precise pages to crawl. We'll discuss more about these tactics later, but let's begin by adding categories to the simple model designs that we created earlier.

Even though our Catalog model is relatively simple, we must make some design decisions before adding our category information. First, we have designed Catalog so that our e-commerce site can produce different catalogs for different scenarios. Each scenario, however, may have different category requirements.

Suppose our fictitious cranberry business, CranStore.com, wants to create a special catalog for the holiday season, when it begins selling numerous gifts and decorative items such as cranberry garland, dried cranberry ornaments, cranberry scented candles and the like. The majority of these special holiday gifts are not available year-round. However, some products will be available in other catalogs at different times of the year—for example, the very popular cranberry-scented candles.

We need to be able to support this use-case. In order to do so, we have to structure our models in a way that may feel awkward at first, but ultimately allows for great flexibility. Let's write a category model called CatalogCategory and add it to our products application's models.py:

class CatalogCategory(models.Model):        
   catalog = models.ForeignKey('Catalog',
                                related_name='categories')
   parent = models.ForeignKey('self', blank=True, null=True,
                               related_name='children')        
   name = models.CharField(max_length=300)
   slug =  models.SlugField(max_length=150)
   description = models.TextField(blank=True)
Categorizing products

In addition, we can now add a relationship between the Product model we wrote earlier and our new CatalogCategory model. The full, updated model appears as follows:

class Product(models.Model):
    category = models.ForeignKey('CatalogCategory', 
                                 related_name='products')
    name = models.CharField(max_length=300)
    slug = models.SlugField(max_length=150)
    description = models.TextField()
    photo = models.ImageField(upload_to='product_photo',
                              blank=True)
    manufacturer = models.CharField(max_length=300,
                                    blank=True)
    price_in_dollars = models.DecimalField(max_digits=6,
                                           decimal_places=2)

There are a couple of big changes here, so let's tackle the CatalogCategory first. This model creates a relationship to our earlier Catalog model, but also includes a ForeignKey relationship to itself. This is called a recursive relationship and is designed as a simple way of creating category hierarchies. A category is a top-level category if it has no parent relationship to other category. Otherwise, it is a sub-category.

The second change is the addition of the ForeignKey to a category on our Product model. An initial design inclination here is to relate products directly to their catalog. We even discussed this design earlier in the chapter, and it would be great for simple catalogs where we didn't need the extra organization functionality of categories.

However, when categories and sub-categories get involved, the design has the potential to become seriously complex. This approach to our Product model allows us to manage a single relationship between products and their categories, thus keeping it relatively simple. This relationship is also implicitly a relationship between our product and a catalog. We still have access to the catalog our product lives in, via the category.

Another advantage of this design is that it remains extremely easy for non-developers to create products, catalogs, and complicated category structures, all within the built-in Django admin tool. As illustrated in the screenshots throughout this chapter, this model design gives us an extremely intuitive admin interface.

One final note about the above code: the default description when CatalogCategory model objects are printed or displayed in the admin is not particularly helpful. Let's add a custom __unicode__ method to this model that prints a more informative display of our categories. This method will include the parent category information if we're working with a sub-category, as well as the catalog to which the category belongs.

def __unicode__(self):
    if self.parent:
        return u'%s: %s - %s' % (self.catalog.name,                   
                                 self.parent.name, 
                                 self.name)
        return u'%s: %s' % (self.catalog.name, self.name) 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset