在Django中生成唯一的slug

4
我看到了许多生成唯一slug的不同方法:示例1示例2示例3示例4,等等。
我想在保存一个ModelForm时创建唯一的slug。如果我的模型如下:
class Phone(models.Model):
    user = models.ForeignKey(User)
    slug = models.SlugField(max_length=70, unique=True)
    year = models.IntegerField()
    model = models.ForeignKey('Model')
    series = models.ForeignKey('Series')

假设Phone对象具有以下值(通过提交的ModelForm):

Phone.user = dude
Phone.year = 2008
Phone.model = iphone
Phone.series = 4S

我希望这个对象的URL呈现为:
http://www.mysite.com/phones/dude-2008-iphone-4S 

我知道应该通过信号或重写保存方法来使用 slugify 来实现这一点。但是如果用户 dude 创建了第二个 2008 年 iPhone 4S 对象,创建唯一的 slug 的最佳方法是什么?我希望附加对象的 URL 看起来像:

http://www.mysite.com/phones/dude-2008-iphone-4S-2

并且

http://www.mysite.com/phones/dude-2008-iphone-4S-3
http://www.mysite.com/phones/dude-2008-iphone-4S-4
#...etc ...

经过谷歌搜索,似乎有多种不同的方法可以在 Django 中创建 slug,这使得在试图确定最佳实践时感到困惑。

非常感谢您对此问题的任何建议和澄清!

2个回答

3

首先,将字段命名为“模型”是个糟糕的想法,这只会引起混淆。寻找替代方案是一个好主意。

最简单的解决方案是在pre_save信号中设置slug:

from django.db.models.signals import pre_save
from django.template.defaultfilters import slugify


def phone_slug(sender, instance, **kwargs):
    slug = u'%s-%s-%s-%s' % (slugify(instance.user.username), instance.year,
        slugify(instance.model), slugify(instance.series))
    instance.slug = slug

    if instance.pk:
        other_phones = Phone.objects.exclude(pk=instance.pk)
    else:
        other_phones = Phone.objects.all()

    i = 2
    exists = other_phones.filter(slug=instance.slug).count() > 0
    while exists:
        instance.slug = u'%s-%s' % (slug, i)
        i++
pre_save.connect(phone_slug, sender=Phone)

或者使用django-autoslug,它的用法大概是这样:

slug = AutoSlugField(unique_with=['user__username', 'year', 'model__name', 'series__name'])

感谢您的回应@jpic。我尝试使用unique_with和您描述的参数来实现autoslugfield,但是slug生成不正确。在这种情况下,slug由模型的名称生成,即slug为“Phone”,这不是期望的结果。也许我在我的实现中错过了什么.. 感谢任何额外的想法。 - Nick B
我说过“类似于”,但我还没有阅读文档并测试您的具体用例,您有阅读文档吗?此外,我添加了一个更简单的解决方案(不需要阅读文档)。 - jpic
是的,我已经阅读了文档,但还没有找到解决我的问题的答案。我将尝试您提供的其他解决方案,并告诉您结果。非常感谢! - Nick B

2

我最终使用了这个Django代码片段来覆盖我的models.py文件中Phone模型的保存方法:

def save(self, **kwargs):
    slug_str = "%s %s %s %s" % (self.user, self.year, self.model, self.series)
    unique_slugify(self, slug_str)
    super(Phone, self).save()

但要感谢jpic的贡献。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接