How to create a unique slug in Django

后端 未结 12 500
栀梦
栀梦 2020-12-04 22:17

I am trying to create a unique slug in Django so that I can access a post via a url like this: http://www.example.com/buy-a-new-bike_Boston-MA-02111_2

The relevant m

相关标签:
12条回答
  • 2020-12-04 22:36

    Here are a couple functions that I use. You pass in the model instance and the desired title into unique_slugify which will add the slug if it doesn't exist, otherwise it will continue trying to append a 4 digit random string until it finds a unique one.

    import string
    from django.utils.crypto import get_random_string
    
    def unique_slugify(instance, slug):
        model = instance.__class__
        unique_slug = slug
        while model.objects.filter(slug=unique_slug).exists():
            unique_slug = slug + get_random_string(length=4)
        return unique_slug
    

    I usually use it by overriding the model save method.

    class YourModel(models.Model):
        slug = models.SlugField()
        title = models.CharField()
    
        def save(self, *args, **kwargs):
            if not self.slug:
                self.slug = unique_slugify(self, slugify(self.title))
            super().save(*args, **kwargs)
    
    0 讨论(0)
  • 2020-12-04 22:38

    If you are thinking of using an app to do it for you, here is one.

    https://github.com/un33k/django-uuslug

    UUSlug = (``U``nique + ``U``code Slug)
    
    
    Unicode Test Example
    =====================
    from uuslug import uuslug as slugify
    
    s = "This is a test ---"
    r = slugify(s)
    self.assertEquals(r, "this-is-a-test")
    
    s = 'C\'est déjà l\'été.'
    r = slugify(s)
    self.assertEquals(r, "c-est-deja-l-ete")
    
    s = 'Nín hǎo. Wǒ shì zhōng guó rén'
    r = slugify(s)
    self.assertEquals(r, "nin-hao-wo-shi-zhong-guo-ren")
    
    s = '影師嗎'
    r = slugify(s)
    self.assertEquals(r, "ying-shi-ma")
    
    
    Uniqueness Test Example
    =======================
    Override your objects save method with something like this (models.py)
    
    from django.db import models
    from uuslug import uuslug as slugify
    
    class CoolSlug(models.Model):
        name = models.CharField(max_length=100)
        slug = models.CharField(max_length=200)
    
        def __unicode__(self):
            return self.name
    
        def save(self, *args, **kwargs):
            self.slug = slugify(self.name, instance=self)
            super(CoolSlug, self).save(*args, **kwargs)
    
    Test:
    =====
    
    name = "john"
    c = CoolSlug.objects.create(name=name)
    c.save()
    self.assertEquals(c.slug, name) # slug = "john"
    
    c1 = CoolSlug.objects.create(name=name)
    c1.save()
    self.assertEquals(c1.slug, name+"-1") # slug = "john-1"
    
    0 讨论(0)
  • 2020-12-04 22:41

    from django.utils.text import slugify Helps a lot and has quite clear Concepts. Here one example on How to auto-generate slug by using from django.utils.text import slugify

    utils.py

    from django.utils.text import slugify
    import random
    import string
    
    # Random string generator
    def random_string_generator(size=10, chars=string.ascii_lowercase + string.digits):
        return ''.join(random.choice(chars) for _ in range(size))
    
    # Unique Slug Generator 
    def unique_slug_generator(instance, new_slug=None):
        """
        It assumes your instance has a model with a slug field and a title character (char) field.
        """
        if new_slug is not None:
            slug = new_slug  
        else:
            slug = slugify(instance.title)  
    
        Klass = instance.__class__
    
        qs_exists = Klass.objects.filter(slug=slug).exists()
    
        if qs_exists:
            new_slug = "{slug}-{randstr}".format(slug=slug, randstr=random_string_generator(size=4))
            return unique_slug_generator(instance, new_slug=new_slug)
        return slug
    

    models.py

    from django.db.models.signals import pre_save # Signals
    # import the unique_slug_generator from .utils.py 
    from .utils import unique_slug_generator
    
    class Product(models.Model):
        title  = models.CharField(max_length=120)
        # set blank to True
        slug  = models.SlugField(blank=True, unique=True)
    
    def product_pre_save_receiver(sender, instance, *args, **kwargs):
        if not instance.slug:
            instance.slug = unique_slug_generator(instance)
    
    
    pre_save.connect(product_pre_save_receiver, sender=Product)
    

    Django documentation explains Django.utils.text import slugify to generate slug automatically. You can read more detail here

    After implementing the code, while creating product, you may leave the slug field blank, which will be further aquired with auto generated slug for the product which will be unique in this case.

    0 讨论(0)
  • 2020-12-04 22:42

    This is the simple and small code i am using for generating unique slug, you only need one field to create your unique slug field

    from random import randint
    
    def save(self, *args, **kwargs):
        if Post.objects.filter(title=self.title).exists():
            extra = str(randint(1, 10000))
            self.slug = slugify(self.title) + "-" + extra
        else:
            self.slug = slugify(self.title)
        super(Post, self).save(*args, **kwargs)
    

    I hope you like this.

    0 讨论(0)
  • 2020-12-04 22:45

    This is a simple implementation that generate the slug from the title, it doesn't depend on other snippets:

    from django.template.defaultfilters import slugify
    
    class Article(models.Model):
        ...
        def save(self, **kwargs):
            if not self.slug:
                slug = slugify(self.title)
                while True:
                    try:
                        article = Article.objects.get(slug=slug)
                        if article == self:
                            self.slug = slug
                            break
                        else:
                            slug = slug + '-'
                    except:
                        self.slug = slug
                        break
    
            super(Article, self).save()
    
    0 讨论(0)
  • 2020-12-04 22:47

    Try this, worked out for me,welcome in advance:

    class Parcel(models.Model):
        title = models.CharField(max_length-255)
        slug = models.SlugField(unique=True, max_length=255)
        weight = models.IntegerField()
        description = models.CharField(max_length=255)
        destination = models.CharField(max_length=255)
        origin = models.CharField(max_length=255)
    
        def __str__(self):
            return self.description
    
        def save(self, *args, **kwargs):
            if not self.slug:
                t_slug = slugify(self.title)
                startpoint = 1
                unique_slug = t_slug
                while Parcel.objects.filter(slug=unique_slug).exists():
                    unique_slug = '{} {}'.format(t_slug, origin)
                    origin += 1
                self.slug = unique_slug
            super().save(*args, **kwargs)
    
    0 讨论(0)
提交回复
热议问题