CookBook - Data Model

A "category" Data Model

Description

I like to have parent/child categories for my documents and weblog entries. I also am a fan of simplicity. This recipe lets you create new categories, and children of categories while providing an intuitively obvious presentation to the user. A parent category of 'Development' with a child category of 'Python' will be displayed as 'Development :: Python'. Using that example, other data models/content types that utilize this code will have drop-downs in the admin interface with entries of 'Development' and 'Development :: Python'

Code

class Category(models.Model):
        name = models.CharField(core=True, maxlength=200)
        slug = models.SlugField(prepopulate_from=('name',))
        parent = models.ForeignKey('self', blank=True, null=True, related_name='child')
        description = models.TextField(blank=True,help_text="Optional")
        
        class Admin:
                list_display = ('name', '_parents_repr')
        
        def __str__(self):
                p_list = self._recurse_for_parents(self)
                p_list.append(self.name)
                return self.get_separator().join(p_list)
        
        def get_absolute_url(self):
                if self.parent_id:
                        return "/tag/%s/%s/" % (self.parent.slug, self.slug)
                else:
                        return "/tag/%s/" % (self.slug)
        
        def _recurse_for_parents(self, cat_obj):
                p_list = []
                if cat_obj.parent_id:
                        p = cat_obj.parent
                        p_list.append(p.name)
                        more = self._recurse_for_parents(p)
                        p_list.extend(more)
                if cat_obj == self and p_list:
                        p_list.reverse()
                return p_list
                
        def get_separator(self):
                return ' :: '
        
        def _parents_repr(self):
                p_list = self._recurse_for_parents(self)
                return self.get_separator().join(p_list)
        _parents_repr.short_description = "Tag parents"
        
        def save(self):
                p_list = self._recurse_for_parents(self)
                if self.name in p_list:
                        raise validators.ValidationError("You must not save a category in itself!")
                super(Category, self).save()

See Also

http://www.djangoproject.com/documentation/model_api/

http://www.djangoproject.com/documentation/models/m2o_recursive/

http://www.djangoproject.com/documentation/models/m2m_and_m2o/

Last modified 17 years ago Last modified on Mar 17, 2007, 9:56:42 AM

Attachments (1)

Download all attachments as: .zip

Note: See TracWiki for help on using the wiki.
Back to Top