# Exports
__all__ = (
"unique_slugify",
)
# Functions
[docs]def unique_slugify(record, value, callback=None, field="slug", queryset=None):
"""Get a unique slug for a model instance.
:param record: The model instance.
:param value: The value to be slugged.
:type value: str
:param callback: The function that converts the value to a slug.
:type callback: callable
:param field: The name of the slug field.
:type field: str
:param queryset: The queryset to use for finding duplicates. This will default to all records of the given record's
model.
:type queryset: django.db.models.QuerySet
:rtype: str
"""
# Set the callback.
from django.utils.text import slugify
_callback = callback or slugify
# Get the field instance for the slug field.
# noinspection PyProtectedMember
slug_field = record._meta.get_field(field)
# Get the initial value.
initial_slug = _callback(value)[:slug_field.max_length]
# Get the queryset.
# noinspection PyProtectedMember
qs = queryset or record.__class__._default_manager.all()
if record.pk:
qs = qs.exclude(pk=record.pk)
# Find a unique slug.
count = 1
slug = initial_slug
while True:
if not qs.filter(**{field: slug}).exists():
break
slug += "%s" % count
count += 1
return slug