If you want unique values for a slug field, but don't want to bother the user with error messages, this function can be put into a model's save function to automate unique slugs. It works by appending an integer counter to duplicate slugs.
The item's slug field is first prepopulated by slugify-ing the source field. If that value already exists, a counter is appended to the slug, and the counter incremented upward until the value is unique.
For instance, if you save an object titled Daily Roundup, and the slug daily-roundup is already taken, this function will try daily-roundup-2, daily-roundup-3, daily-roundup-4, etc, until a unique value is found.
Call from within a model's custom save() method like so:
`unique_slug(item, slug_source='field1', slug_field='field2')`
where the value of field slug_source will be used to prepopulate the value of slug_field.
Comments appreciated!
This is just a very short (and mostly useless on it's own) example of how the built in slugify filter can be used in a Python script to generate slugs. It was pulled from a script I've written to pull in items from Upcoming.org's API.
I post it because "sunturi" posted [Snippet #29](http://www.djangosnippets.org/snippets/29/), which duplicates the functionality of the built-in slugify filter. In the comments of that snippet, santuri (and others) seem to believe that template filters can only be used within templates. This is incorrect, and I think it's important people understand they can be used elsewhere.
sunturi's snippet does remove prepositions from values before slugifying them, so if you need that, his code will work work. But if all you need is slugification, the built-in slugify filter will work fine -- in a Python script, as well as in a template.
- template
- filter
- django
- slug
- built-in
*I suppose I'm kind of stubborn, but I prefer to use underscores to replace spaces and other characters. Of course, that shouldn't hold you back from using the build-in slugify filter :)*
** Forcing the slug to use ASCII equivalents: **
Transforming titles like "Äës" to slugs like "aes" was kind of a trial and error job. It now works for me. I hope `_string_to_slug(s):` proves a rather stable solution. Yet the worst-case scenario is that such characters are lost, I guess that is acceptable.
Other ways of dealing with this problem can be found at [Latin1 to ASCII at Activestate](http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/251871) or in the comments below.
**How to use:**
The slug fields in your model must have prepopulate_from set, the fields specified in it are used to build the slug.
To prevent duplicates, a number is added to the slug if the slug already exists for the current field in another, previous, object. I guess there should be a cleaner way to distinguish between creating a new db entry or updating an existing one, sadly, the db back-end is kind of a black-box to me. At least this works ;)
I choose not to alter the slug on an update to keep urls more bookmarkable. You could even extend this further by only updating the slug field if it hasn't been assigned a value.