Django

Code

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/

Attachments