32

我正在尝试在 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"
  • 城市 = “波士顿”
  • 状态码 = "MA"

样本需求记录:

  • title = "买一辆新自行车"
  • us_zip = "02111"
  • slug =“购买新自行车_波士顿-MA-02111_2”(需要)

关于如何创建这种独特的蛞蝓的任何提示?其组成为:

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

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

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

谢谢!

更新

我已经为它的 UUIDField 使用了 django-extensions,所以如果它也可以用于它的 AutoSlugField 那就太好了!

4

11 回答 11

44

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

slug 将是带有 blank=True 的 Django SlugField,但在 save 方法中强制执行 slug。

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

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等这样的蛞蝓。输出可能略有不同,但您始终可以浏览代码片段并根据您的需要进行自定义。

于 2010-09-28T19:57:36.697 回答
8

我的小代码:

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()
于 2011-06-30T13:34:41.290 回答
6

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

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"
于 2011-05-31T18:50:22.453 回答
4

这是我使用的几个函数。您传入模型实例和所需的标题unique_slugify,如果它不存在,它将添加 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)
于 2020-08-05T16:40:03.643 回答
4

这是我用来生成唯一 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)

我希望你喜欢这个。

于 2020-08-16T10:31:30.253 回答
2

这是一个从标题生成 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()
于 2016-01-26T19:12:17.443 回答
2

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,
    })
于 2016-01-27T12:00:52.840 回答
1

嗨,你能试试这个功能吗

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 save(self, *args, **kwargs):
       self.slug =get_unique_slug(self.id,self.title,Training.objects)
       return super(Training, self).save(*args, **kwargs)

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
于 2018-08-09T14:09:10.650 回答
1

from django.utils.text import slugify 帮助很大,概念也比较清晰。这里有一个关于如何使用 from django.utils.text import slugify 自动生成 slug 的示例

实用程序.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

模型.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 文档解释了 Django.utils.text 导入 slugify 以自动生成 slug。您可以在此处阅读更多详细信息

实现代码后,在创建产品时,您可以将 slug 字段留空,这将通过自动生成的产品 slug 进一步获取,在这种情况下将是唯一的。

于 2019-11-14T09:09:51.197 回答
-1
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()
于 2010-09-29T07:37:51.053 回答
-1

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

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)
于 2019-05-20T00:08:22.223 回答