如何在 Django 中创建独特的 slug

发布于 2024-09-25 06:52:06 字数 1394 浏览 5 评论 0原文

我正在尝试在 Django 中创建一个独特的 slug,以便我可以通过如下网址访问帖子: http://www.example.com/buy-a-new-bike_Boston -MA-02111_2

相关型号:

class ZipCode(models.Model):
    zipcode = models.CharField(max_length=5)
    city = models.CharField(max_length=64)
    statecode = models.CharField(max_length=32)

class Need(models.Model):
    title = models.CharField(max_length=50)
    us_zip = models.CharField(max_length=5)
    slug = ?????

    def get_city():
        zip = ZipCode.objects.get(zipcode=self.us_zip)
        city = "%s, %s %s" % (zip.city, zip.statecode, zip.zipcode)
        return city

邮政编码记录示例:

  • zipcode = "02111"
  • city = "Boston"
  • statecode = "MA"

需要记录示例:

  • title = "买一辆新自行车"
  • us_zip = "02111"
  • slug =“buy-a-new-bike_Boston-MA-02111_2”(所需)

关于如何创建这个独特的slug有什么建议吗?它的组成是:

  • Need.title + "_" + Need.get_city() + "_" + 一个可选的递增整数以使其唯一。所有空格均应替换为“-”。

注意:上面我想要的 slug 假设 slug“buy-a-new-bike_Boston-MA-02111”已经存在,这就是它附加的“_2”以使其唯一。

我尝试过 django-extensions,但似乎它只能使用一个字段或字段元组来构造唯一的 slug。我需要传入 get_city() 函数以及标题和城市之间的“_”连接器。有人解决了这个问题并愿意分享吗?

谢谢你!

更新

我已经在其 UUIDField 中使用 django-extensions,因此如果它也可用于其 AutoSlugField,那就太好了!

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 models:

class ZipCode(models.Model):
    zipcode = models.CharField(max_length=5)
    city = models.CharField(max_length=64)
    statecode = models.CharField(max_length=32)

class Need(models.Model):
    title = models.CharField(max_length=50)
    us_zip = models.CharField(max_length=5)
    slug = ?????

    def get_city():
        zip = ZipCode.objects.get(zipcode=self.us_zip)
        city = "%s, %s %s" % (zip.city, zip.statecode, zip.zipcode)
        return city

A sample ZipCode record:

  • zipcode = "02111"
  • city = "Boston"
  • statecode = "MA"

A sample Need record:

  • title = "buy a new bike"
  • us_zip = "02111"
  • slug = "buy-a-new-bike_Boston-MA-02111_2" (desired)

Any tips as to how to create this unique slug? Its composition is:

  • Need.title + "_" + Need.get_city() + "_" + an optional incrementing integer to make it unique. All spaces should be replaced with "-".

NOTE: My desired slug above assumes that the slug "buy-a-new-bike_Boston-MA-02111" already exists, which is what it has the "_2" appended to it to make it unique.

I've tried django-extensions, but it seems that it can only take a field or tuple of fields to construct the unique slug. I need to pass in the get_city() function as well as the "_" connector between the title and city. Anyone solved this and willing to share?

Thank you!

UPDATE

I'm already using django-extensions for its UUIDField, so it would be nice if it could also be usable for its AutoSlugField!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

青衫负雪 2024-10-02 06:52:06

我使用这个 snippet 来生成独特的 slug,我典型的保存方法如下所示,

slug 将是 Django SlugField 与Blank=True 但在保存方法中强制执行 slug。

Need 模型的典型保存方法可能如下所示

def save(self, **kwargs):
    slug_str = "%s %s" % (self.title, self.us_zip) 
    unique_slugify(self, slug_str) 
    super(Need, self).save(**kwargs)

,这将生成类似 buy-a-new-bike_Boston-MA-02111 、 buy-a-new-bike_Boston-MA-02111-1 等的 slug。输出可能略有不同,但您始终可以查看代码片段并根据您的需求进行自定义。

I use this snippet for generating unique slug and my typical save method look like below

slug will be Django SlugField with blank=True but enforce slug in save method.

typical save method for Need model might look below

def save(self, **kwargs):
    slug_str = "%s %s" % (self.title, self.us_zip) 
    unique_slugify(self, slug_str) 
    super(Need, self).save(**kwargs)

and this will generate slug like buy-a-new-bike_Boston-MA-02111 , buy-a-new-bike_Boston-MA-02111-1 and so on. Output might be little different but you can always go through snippet and customize to your needs.

或十年 2024-10-02 06:52:06

我的小代码:

def save(self, *args, **kwargs):
    strtime = "".join(str(time()).split("."))
    string = "%s-%s" % (strtime[7:], self.title)
    self.slug = slugify(string)
    super(Need, self).save()

My little code:

def save(self, *args, **kwargs):
    strtime = "".join(str(time()).split("."))
    string = "%s-%s" % (strtime[7:], self.title)
    self.slug = slugify(string)
    super(Need, self).save()
白云悠悠 2024-10-02 06:52:06

这是我使用的几个函数。您将模型实例和所需的标题传递到 unique_slugify 中,如果 slug 不存在,它将添加该 slug,否则它将继续尝试附加 4 位随机字符串,直到找到唯一的字符串。

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

我通常通过重写模型 save 方法来使用它。

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)

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)
酒与心事 2024-10-02 06:52:06

如果您正在考虑使用应用程序来为您做到这一点,这里有一个。

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"

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"
初心 2024-10-02 06:52:06

这是我用来生成独特的 slug 的简单而小的代码,
你只需要一个字段来创建你独特的slug字段

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)

我希望你喜欢这个。

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.

鹤仙姿 2024-10-02 06:52:06

这是一个从标题生成 slug 的简单实现,它不依赖于其他片段:

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()

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()
狼亦尘 2024-10-02 06:52:06

Django 提供了一个 SlugField 模型字段来让您更轻松地完成此操作。这是“博客”应用程序中的一个示例,

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField(blank=True)

    slug = models.SlugField(unique=True)

    @models.permalink
    def get_absolute_url(self):
        return 'blog:post', (self.slug,)

请注意,我们为 slug 字段设置了 unique=True - 在这个项目中,我们将通过其 slug 查找帖子,因此我们需要确保它们是唯一的。我们的应用程序的views.py 可能如下所示:

from .models import Post

def post(request, slug):
    post = get_object_or_404(Post, slug=slug)

    return render(request, 'blog/post.html', {
        'post': post,
    })

Django provides a SlugField model field to make this easier for you. Here's an example of it in a "blog" app's

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField(blank=True)

    slug = models.SlugField(unique=True)

    @models.permalink
    def get_absolute_url(self):
        return 'blog:post', (self.slug,)

Note that we've set unique=True for our slug field — in this project we will be looking up posts by their slug, so we need to ensure they are unique. Here's what our application's views.py might look like to do this:

from .models import Post

def post(request, slug):
    post = get_object_or_404(Post, slug=slug)

    return render(request, 'blog/post.html', {
        'post': post,
    })
雨落□心尘 2024-10-02 06:52:06

from django.utils.text import slugify 有很大帮助并且概念非常清晰。
这里有一个关于如何使用 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)

自动生成 slug 的示例Django 文档解释了 Django.utils.text import slugify 自动生成 slug 。您可以在此处

之后 阅读更多详细信息实现代码,在创建产品时,您可以将 slug 字段留空,这将通过自动生成的产品 slug 进一步获取,在本例中该字段是唯一的。

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.

淡写薰衣草的香 2024-10-02 06:52:06

您好,您可以尝试一下这个功能吗

class Training(models.Model):
    title = models.CharField(max_length=250)
    text = models.TextField()
    created_date = models.DateTimeField(
    auto_now_add=True, editable=False, )
    slug = models.SlugField(unique=True, editable=False, max_length=250)

    def __unicode__(self):
       return self.title

    def get_unique_slug(id,title,obj):
      slug = slugify(title.replace('ı', 'i'))
      unique_slug = slug
      counter = 1
      while obj.filter(slug=unique_slug).exists():
         if(obj.filter(slug=unique_slug).values('id')[0]['id']==id):
             break
         unique_slug = '{}-{}'.format(slug, counter)
         counter += 1
      return unique_slug.  

    def save(self, *args, **kwargs):
       self.slug =self.get_unique_slug(self.id,self.title,Training.objects)
       return super(Training, self).save(*args, **kwargs)

Hi can you tried this function

class Training(models.Model):
    title = models.CharField(max_length=250)
    text = models.TextField()
    created_date = models.DateTimeField(
    auto_now_add=True, editable=False, )
    slug = models.SlugField(unique=True, editable=False, max_length=250)

    def __unicode__(self):
       return self.title

    def get_unique_slug(id,title,obj):
      slug = slugify(title.replace('ı', 'i'))
      unique_slug = slug
      counter = 1
      while obj.filter(slug=unique_slug).exists():
         if(obj.filter(slug=unique_slug).values('id')[0]['id']==id):
             break
         unique_slug = '{}-{}'.format(slug, counter)
         counter += 1
      return unique_slug.  

    def save(self, *args, **kwargs):
       self.slug =self.get_unique_slug(self.id,self.title,Training.objects)
       return super(Training, self).save(*args, **kwargs)
怪我太投入 2024-10-02 06:52:06
 def get_slug(self):
    slug = slugify(self.title.replace("ı", "i"))
    unique = slug
    number = 2

    while Model.objects.filter(slug=unique).exists():
        unique = "{}-{}".format(slug, number)
        number += 1
    return unique
 def get_slug(self):
    slug = slugify(self.title.replace("ı", "i"))
    unique = slug
    number = 2

    while Model.objects.filter(slug=unique).exists():
        unique = "{}-{}".format(slug, number)
        number += 1
    return unique
风苍溪 2024-10-02 06:52:06

对我来说最好的解决方案:

def get_slug(self):
    slug = slugify(self.title)
    unique_slug = slug

    number = 1
    while Recipe.objects.filter(slug=unique_slug).exists():
        unique_slug = f'{slug}-{number}'
        number += 1

    return unique_slug

def save(self, *args, **kwargs):
    if not self.slug:
        self.slug = self.get_slug()
    return super().save(*args, **kwargs)

这段代码可以生成像这样的slug:

  • string-slug
  • string-slug-1 (如果以前的 alredy 存在)
  • string-slug-2 (如果以前的 alredy 存在)
  • 等等...

Best solution for me:

def get_slug(self):
    slug = slugify(self.title)
    unique_slug = slug

    number = 1
    while Recipe.objects.filter(slug=unique_slug).exists():
        unique_slug = f'{slug}-{number}'
        number += 1

    return unique_slug

def save(self, *args, **kwargs):
    if not self.slug:
        self.slug = self.get_slug()
    return super().save(*args, **kwargs)

This code can generate slug like this:

  • string-slug
  • string-slug-1 (if previous alredy exists)
  • string-slug-2 (if previous alredy exists)
  • and so on...
枉心 2024-10-02 06:52:06
class Need(models.Model):
    title = models.CharField(max_length=50)
    us_zip = models.CharField(max_length=5)
    slug = models.SlugField(unique=True)

    def save(self, **kwargs):
        slug_str = "%s %s" % (self.title, self.us_zip) 
        super(Need, self).save()
class Need(models.Model):
    title = models.CharField(max_length=50)
    us_zip = models.CharField(max_length=5)
    slug = models.SlugField(unique=True)

    def save(self, **kwargs):
        slug_str = "%s %s" % (self.title, self.us_zip) 
        super(Need, self).save()
你与昨日 2024-10-02 06:52:06

试试这个,为我解决了,提前欢迎:

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)

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文