Django slugified urls - how to handle collisions?
One thing I never liked about the unique slug fields/methods is that if you have a lot of clashes for a single title, you'll end up running several queries to try and determine an available slug. I know you mentioned you don't want to show the id for non-clashing slugs, but, as far as performance, I think it's the better route to take. To make the URL a little nicer looking, I prefer also to embed the id before the slug, so that a URL takes the form of www.example.com/reviews/1/the-best-thing-ever.
I would recommend something like AutoSlugField. It has a few options available with respect to configuring uniqueness (unique
and unique_with
), and has the added benefit of being able to automatically generate slugs based on another field on your model, if you so choose.
from django.template.defaultfilters import slugifydef slugify_unique(value, model, slugfield="slug"): 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 suffix += 1 """above function is not my code, but i don't remember exactly where it comes fromyou can find many snippets with such solutions searching for 'unique slug' and so"""class ReviewForm(forms.ModelForm): def save(self, user, commit=True): self.instance.slug = slugify_unique(self.cleaned_data['title'], self.Meta.model) review = super(ReviewForm, self).save(commit) review.save() return review class Meta: model = Review
of course change the appropriate names and form definition, but you get the idea :)