为啥在 Django 中使用 SlugField()?
Posted
技术标签:
【中文标题】为啥在 Django 中使用 SlugField()?【英文标题】:Why SlugField() in Django?为什么在 Django 中使用 SlugField()? 【发布时间】:2013-07-03 22:27:13 【问题描述】:Django 有models.SlugField()
,它可以帮助我们创建一些看起来很酷的 url。
我的问题是为什么将其指定为字段
假设我有这个模型
class Blog(models.Model):
title = models.CharField()
如果我想添加 slug,我可以使用
class Blog(models.Model):
title = models.CharField()
def title_slug(self):
return slugify(self.title)
在 urls 我可以使用
(r'^blog/(?P<id>\d+)/(?P<slug>[-\w]+)/$', 'app.views.blog_view'),
在浏览量
中def blog_view(request, id ,slug):
get_object_or_404(Blog, pk=id)
...
网址看起来像
example.com/blog/23/why-iam-here/
促使我采用这种方法的三件事
-
Slug 字段不具有隐式唯一性。
get_object_or_404(Blog, pk=id)
必须比 get_object_or_404(Blog, slug=slug)
快。
向现有模型添加 slug 字段涉及数据迁移。
那么为什么是 SlugField()? ,除了动态生成slug的成本外,上述方法有什么缺点?
【问题讨论】:
【参考方案1】:为什么在 Django 中使用 SlugField()?因为:
-
它对人类友好(例如 /blog/ 而不是 /1/)。
在标题、标题和 URL 中创建一致性是很好的 SEO。
动态生成的 slug 的最大缺点是接受 urls.py 中的 slug 而不使用 slug 来获取正确的对象?这是糟糕的设计。
如果您提供和接受 slug,但不检查它们,那么您有多个 URL 返回相同的内容。所以 /1/useful-slug/ 和 /1/this-is-a-bs-slug/ 都会返回同一个页面。
这很糟糕,因为它不会让人类的生活变得轻松。您的访问者必须提供一个 id 和一些多余的东西。重复的页面是搜索引擎的噩梦。哪一页是正确的?重复的页面最终排名较低。见https://support.google.com/webmasters/answer/40349?hl=en(最后一个)
您可以争辩说您始终如一地实现自己生成的精美链接,但人们和机器人一直在猜测 URL(请参阅您的日志文件)。当你接受所有的蛞蝓时,人类和机器人总是猜对的。
同时将 slug 保存到 db 可以节省处理能力。您一次生成 slug 并重复使用它。每次查找或生成 slug 会更(低)效吗?
管理中的 Slug 字段对于让编辑者有机会编辑 slug 很有用。也许是为了提供标题中没有但仍然值得一提的额外信息。
奖励:更新迁移的数据:
from django.template.defaultfilters import slugify
for obj in Blog.objects.filter(slug=""):
obj.slug = slugify(obj.title)
obj.save()
【讨论】:
*** 使用重定向(我喜欢它):***.com/questions/17495299/this-will-be-replaced不客气! 如果你不打算写两次相同的东西,或者你真的不关心不一致,我会说蛞蝓是没用的。节省处理能力?生成一个 url 真的没什么,而且在你的数据库中有一个冗余列更烦人。我真的不明白这个 slug() 的意义【参考方案2】:Slug 字段不具有隐式唯一性。
CharField
没有隐含的唯一性。如果要确保每一行在数据库级别是唯一的,则需要指定 unique=True
。您必须同时使用 CharField
和 SlugField
来执行此操作,因此两者都没有优势
get_object_or_404(Blog, pk=id) 必须比 get_object_or_404(Blog, slug=slug) 快。
由于主键上的索引,可能会有非常小的差异,但可能可以忽略不计。这与使用 CharField
与 SlugField
无关 - 您刚刚创建了一个不同的 URL,它采用 id
并使用它来进行查找。
向现有模型添加 slug 字段涉及数据迁移。
将CharField
添加到现有模型也需要数据迁移,因此这里没有优势。
SlugFields
只是 CharField
加上额外的验证。 Look at the code。你正在打破 Django 的 DRY 黄金法则——不要重复自己。
此外,如果您只使用CharField
,您不会在表单级别获得任何验证,因此您可以非常轻松地创建一个不符合 slugs 验证的“slug”,即它可能有空格或 URL 中不允许的字符。
同样使用这种方法,如果您更改标题,则您的 URL 已更改,现在您所有的旧链接都已失效。拥有一个 slug 字段可以防止这种情况发生。
您在这里给自己制造更多麻烦 - 只需使用 SlugField
【讨论】:
感谢您的宝贵意见,关于验证和干燥的要点很好。但我的实际问题不是 CharField 和 slugfield 之间的区别,而是在数据库中拥有 SlugField 并动态生成一个的区别。 我已经回答说:“SlugFields 只是带有额外验证的 CharField”——在数据库级别没有区别 SlugField 默认不创建数据库索引吗? docs.djangoproject.com/en/1.7/ref/models/fields/#slugfield SlugField “暗示将 Field.db_index 设置为 True。”所以,它应该默认被索引。【参考方案3】:我正在制作一个多租户日历应用。如果日历 url 类似于:/calendar/id/,其中 id 是连续的整数,那么黑客可能会猜测 id 并找到比我想要的更多的关于我的业务的信息。通过使用 url /calendar/slug/ 找到所有日历要困难得多。
【讨论】:
以上是关于为啥在 Django 中使用 SlugField()?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Django 通用列表视图类中使用 slugfield 创建链接?
Django奇怪的SlugField验证,在clean()之前没有引发错误,返回了未清理的数据