from django.db import models from django.utils.text import slugify from django.utils.translation import ugettext_lazy as _ class Taxonomy(models.Model): name = models.CharField( verbose_name=_('Name'), max_length=250, help_text=_('Taxonomy Name'), unique=True, db_index=True, ) slug = models.SlugField( verbose_name=_('Slug'), max_length=250, unique=True, # Should be true already db_index=True, # Should be true by implication # https://docs.djangoproject.com/en/1.8/ref/models/fields/#slugfield ) def save(self, *args, **kwargs): self.slug = slugify(self.name) super(Taxonomy, self).save(*args, **kwargs) def __unicode__(self): return self.name # My thoughts on how this grows... # # multiplicity = models.CharField( # ... # choices=( # ('optional', _('Zero or One')), # ('multiple', _('Zero or More')), # ) # ) # # vocabulary = models.CharField( # ... # choices=( # ('fixed', _('Not modifiable by any user, system only')), # ('closed', _('Only admin users who have permission to define and edit taxonomies')), # ('open', _('Any user who has permission to use taxonomies')), # ) # ) # To do Categories, you use 'optional' and 'closed', # to do free tagging use 'multiple' and 'open' class TermManager(models.Manager): def by_taxonomy(self, taxonomy, term_name): """ Fetch an existing Term by its name and its Taxonomy slug which, together should be unique together. args: taxonomy: [Taxonomy|string] Taxonomy instance or taxonomy slug. term_name: string: the name of an existing term returns: The term object with the given name in the given Taxonomy. throws: DoesNotExist if no Term matches the given combination ValueError if taxonomy is not one of the allowed types """ if isinstance(taxonomy, basestring): taxonomy_slug = taxonomy elif isinstance(taxonomy, Taxonomy): taxonomy_slug = taxonomy.slug else: raise ValueError( "taxonomy must be a Taxonomy instance " "or a valid taxonomy slug") return self.get(taxonomy__slug=taxonomy_slug, name=term_name) class Term(models.Model): name = models.CharField( verbose_name=_('Name'), max_length=250, help_text=_('Tag or Category Name'), db_index=True, ) taxonomy = models.ForeignKey( Taxonomy, verbose_name=_('Taxonomy'), related_name="%(app_label)s_%(class)s_term" ) long_name = models.TextField( verbose_name=_('Long Name'), blank=True, ) def __unicode__(self): return "{}:{}".format( self.taxonomy.name, self.name ) # Custom Manager objects = TermManager() class Meta: unique_together = ('name', 'taxonomy') index_together = ['name', 'taxonomy']