2

I got the following models:

class Category(models.Model):
    name = models.CharField(max_length=255)
    parent = models.ForeignKey("self", blank=True, null=True)

    class Meta:
        verbose_name = _("category")
        verbose_name_plural = _("categories")

     def __unicode__(self):
         return self.name


class Item(models.Model):
     name = models.CharField(max_length=100, verbose_name=_("name"))
     keywords = models.CharField(max_length=255, verbose_name=_("keywords"))
     category = models.ForeignKey(Category)

     class Meta:
         abstract = True
         verbose_name = _('item')
         verbose_name_plural = _('items')


class Product(Item):
    price = models.DecimalField(decimal_places=2, max_digits=8, verbose_name=_("price"))
    brand = models.ForeignKey(Brand, verbose_name=_("brand"))
    article_number = models.CharField(max_length=255, verbose_name=_("article_number"))

    def __unicode__(self):
         return self.name

    class Meta:
        verbose_name = _('product')
        verbose_name_plural = _('products')

Let's say i have the following categories in the database:

ID     NAME      PARENT_ID
1      Products       null
2      Phones            1
3      iPhones           2

I can get the top category by doing the following:

#This is a product with the category "iPhones"
product.category.parent.parent

But that's not nice because a product can be x numbers of categories deep.

How can I get all the related categories in an array or something?

Wanted output = [iPhones, Phones, Products]
Anish Shah
  • 7,669
  • 8
  • 29
  • 40
JOSEFtw
  • 9,781
  • 9
  • 49
  • 67

1 Answers1

4

Write a Model Property Method for the item class:

  class Item(models.Model):
     @property
     def all_categories(self):
        categories = []
        current_category = self.category
        while current_category is not None:
            categories.append(current_category)
            current_category = current_category.parent
        return categories
        #optional return reversed list:
        #return list(reversed(categories))

Now you can get the desired list with

product.all_categories
Dr.Elch
  • 2,105
  • 2
  • 17
  • 23
  • 1
    Thank you very much! I managed to come up with a solution myself, but I will switch to your code right away :) Heres my solution. `def get_all_categories(self, cat_obj): category_list = [] if cat_obj.parent_id: c = cat_obj.parent category_list.append(c) more = self.get_all_categories(c) category_list.extend(more) if cat_obj == self and category_list: category_list.reverse() category_list.append(self) return category_list` – JOSEFtw Mar 19 '14 at 13:16