from django.db import models from django.utils.crypto import get_random_string try: from django_scopes import scopes_disabled except ImportError: scopes_disabled = False class RandomSlugMixin(models.Model): """ some alternatives for slug_chars: abcdeghjkpqrsxyz23456789 # 24 chars, max clarity while being all lowercase ABCDGHKLMNQRTabcdeghjr23456789 # 30 chars, max clarity mixed case abcdefghijkmnpqrstuwxyz123467890 # 32 chars, all lowercase """ slug_chars = 'abcdefghijkmnpqrstuwxyz123467890' class Meta: abstract = True slug = models.CharField(max_length=6, unique=True) def save(self, **kwargs): self.generate_slug() super().save(**kwargs) def generate_slug(self): if not self.slug: self.slug = self.generate_new_slug() def generate_new_slug(self): slug = get_random_string(self.slug_length, self.slug_chars) if self.__class__.objects.filter(slug=slug).exists(): return self.generate_new_slug() return slug @property def slugs_available(self): return self.slug_count_total - self.__class__.objects.count() @property def slug_count_total(self): return len(self.slug_chars) ** self.slug_length @property def slug_length(self): return self.__class__._meta.get_field('slug').max_length if scopes_disabled: generate_new_slug = scopes_disabled(generate_new_slug) slugs_available = scopes_disabled(slugs_available) class RandomSlugPKMixin(RandomSlugMixin): slug = models.CharField(max_length=6, unique=True, primary_key=True) class Meta: abstract = True