Version 1 (modified by 19 years ago) ( diff ) | ,
---|
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(Tag, self).save()
See Also
http://www.djangoproject.com/documentation/model_api/
http://www.djangoproject.com/documentation/models/m2o_recursive/
Attachments (1)
- models.py (1.4 KB ) - added by 19 years ago.
Download all attachments as: .zip