[Django]-Loop over parent ForeignKey

3πŸ‘

βœ…

What you are describing is a tree structure, and iterating over all parent elements of a recursive foreign key relationship is unfortunately a very expensive operation; every lookup for the parent will require one database hit, as the other answers demonstrate methods of doing.

What I would suggest you do instead is use a table structure that allows for efficient tree queries. There are several methods of doing this, but to point you in the right direction I would suggest looking into django-mptt or django-treebeard.

For example, using django-mptt you could achieve this with the following general structure, which will only result in one additional database hit to query for all ancestors of the target category.

from django.db import models
from mptt.models import MPTTModel, TreeForeignKey


class Category(MPTTModel):
    name = models.CharField(max_length=255)
    parent = TreeForeignKey('self', null=True, blank=True, related_name='children')

    def __unicode__(self):
        ancestors = self.get_ancestors(ascending=False, include_self=True)
        return ' -> '.join(category.name
                           for category in ancestors)
πŸ‘€Daniel Naab

3πŸ‘

How about..

   def __unicode__(self):
       str = self.category
       obj = self
       while obj.parentCateogry:
            str += " " + obj.parentCategory.category 
            obj = obj.parentCategory
       return str
πŸ‘€Aidan Ewen

1πŸ‘

You can do it like this:

class Category(models.Model):
    parentCategory = models.ForeignKey('self', null=True, blank=True,
        related_name="categories")
    category = models.CharField(max_length=255)

    def get_name(self, obj, name=''):
        name += ' - ' + obj.category
        categories = obj.categories.all()
        if categories:
            for category in categories:
                name = self.get_name(category, name)
            return name
        else:
            return name

    def __unicode__(self):
        return self.get_name(self).strip(' - ').strip()
πŸ‘€Aamir Rind

Leave a comment