Changes between Initial Version and Version 1 of SlugifyUniquely

11/16/2006 04:15:04 PM (13 years ago)

How to automagically choose a slug unique within a model


  • SlugifyUniquely

    v1 v1  
     1It's common for me to want a unique slug based on a user supplied name of an object. Following the pattern outlined at [ djang-tips-auto-populated-fields], it's easy to get the field populated without user intervention. However, by setting the slug field in the save() method the field isn't validated and thus unique=True restrictions aren't checked. I wrote the following code to attempt to pick slugs which are unique within a particular model. It's certainly not ideal (it suffers from race condition as well as potential for pounding a database with lots of small queries until it finds a good slug field), but it works for my small/mid-sized apps.
     3Feel free to suggest improvements to 'wam-djangowiki' (remove the ' spam' from the address there).
     6def SlugifyUniquely(value, model, slugfield="slug"):
     7        """Returns a slug on a name which is unique within a model's table
     9        This code suffers a race condition between when a unique
     10        slug is determined and when the object with that slug is saved.
     11        It's also not exactly database friendly if there is a high
     12        likelyhood of common slugs being attempted.
     14        A good usage pattern for this code would be to add a custom save()
     15        method to a model with a slug field along the lines of:
     17                from django.template.defaultfilters import slugify
     19                def save(self):
     20                    if not
     21                        # replace with your prepopulate_from field
     22                        self.slug = SlugifyUniquely(, self.__class__)
     23                super(self.__class__, self).save()
     25        Original pattern discussed at
     27        """
     28        suffix = 0
     29        potential = base = slugify(value)
     30        while True:
     31                if suffix:
     32                        potential = "-".join([base, str(suffix)])
     33                if not model.objects.filter(**{slugfield: potential}).count():
     34                        return potential
     35                # we hit a conflicting slug, so bump the suffix & try again
     36                suffix += 1
Back to Top