在 Django 中生成唯一的 slug
Posted
技术标签:
【中文标题】在 Django 中生成唯一的 slug【英文标题】:Generating unique slug in Django 【发布时间】:2012-09-11 06:44:09 【问题描述】:我见过各种不同的方法来生成独特的 slug:Ex. 1、Ex.2、Ex. 3、Ex. 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,这在试图找出最佳实践时一直令人困惑。
非常感谢您对此问题的任何建议和澄清!
【问题讨论】:
【参考方案1】:首先,将字段命名为“模型”是一个坏主意,它只会造成混乱。寻找替代方案是个好主意。
最简单的解决方案是在 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
,这不是预期的结果。也许我在实施过程中遗漏了一些东西。感谢您提供任何其他想法
我说“有点像”,但我还没有阅读文档并测试过您的具体用例,您阅读过文档吗?另外,我添加了一个更简单的解决方案(不需要阅读文档)
是的,我阅读了文档,但还没有找到我的问题的答案。我会尝试您的其他解决方案并让您知道。非常感谢!【参考方案2】:
我最终使用This Django Snippet 覆盖了我的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 的贡献。
【讨论】:
以上是关于在 Django 中生成唯一的 slug的主要内容,如果未能解决你的问题,请参考以下文章