[Django]-How to create random slug in Django

4👍

This happen because your default value is not function that will be called on each save, it’s rather a constant value generated when your app start

An other option would be moving the logic to save method of your model:

    slug = models.SlugField(
        default='',
        editable=False,
        blank=False
    )

    ...

    def save(self, *args, **kwargs):
        if not self.default:
            self.default = secrets.token_urlsafe(64)

        super().save(*args, **kwargs)
👤ahmed

1👍

Change your code to:

def get_token_slug():
    return secrets.token_urlsafe(64)

slug = models.SlugField(
        default=get_token_slug,
        editable=False,
        blank=False,
        unique=True,             # also add this
    )

The problem was that the function call that you give as a default value is computed once and the result is used as a default value in all new instances of this model.

Instead, you should give a callable as a default value, which will then be called when a new instance of the model is created. So just wrap the token_urlsafe call in a function, and give it as an argument (the function, not a call, so without parentheses () )

👤talz

0👍

In terms of creating a unique slug field when saving an instance of your model, you will need to alter your save method so that it can create a slug which has the next available number appended to the end of your slug. It might look something like the below…

Replace MyModel and field_you_are_using_to_slugify as applicable.

def save(self):
    if not self.slug.strip():
        self.slug = slugify(self.field_you_are_using_to_slugify)

    _slug = self.slug
    _count = 1

    while True:
        try:
            MyModel.objects.all().exclude(pk=self.pk).get(slug=_slug)
        except MultipleObjectsReturned:
            pass
        except ObjectDoesNotExist:
            break
        _slug = f"{self.slug}{_count}"
        _count += 1

    self.slug = _slug

    super(MyModel, self).save()

It should be noted however that if you’re after a URL which cannot be interpreted and uses random string generation, then Django provides a UUID field for that purpose. Here is a link to the docs

Leave a comment