Version 5 (modified by 14 years ago) ( diff ) | ,
---|
It'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 and some useful instructions from research papers, 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.
Feel free to suggest improvements to 'wam-djangowiki spam@…' (remove the ' spam' from the address there).
def SlugifyUniquely(value, model, slugfield="slug"): """Returns a slug on a name which is unique within a model's table This code suffers a race condition between when a unique slug is determined and when the object with that slug is saved. It's also not exactly database friendly if there is a high likelyhood of common slugs being attempted. A good usage pattern for this code would be to add a custom save() method to a model with a slug field along the lines of: from django.template.defaultfilters import slugify def save(self): if not self.id: # replace self.name with your prepopulate_from field self.slug = SlugifyUniquely(self.name, self.__class__) super(self.__class__, self).save() Original pattern discussed at http://www.b-list.org/weblog/2006/11/02/django-tips-auto-populated-fields """ suffix = 0 potential = base = slugify(value) while True: if suffix: potential = "-".join([base, str(suffix)]) if not model.objects.filter(**{slugfield: potential}).count(): return potential # we hit a conflicting slug, so bump the suffix & try again suffix += 1