Django有models.SlugField()
这有助于我们创建一些很酷的网址。
我的问题是为什么将它指定为一个字段
假设我有模型
class Blog(models.Model):
title = models.CharField()
如果我想添加slug,我可以使用
class Blog(models.Model):
title = models.CharField()
def title_slug(self):
return slugify(self.title)
我可以使用
(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 /
有三件事让我采用这种方法
get_object_or_404(Blog, pk=id)
必须快于get_object_or_404(Blog, slug=slug)
。为什么SlugField()?除了动态产生段塞的成本外,上述方法有哪些缺点?
答案 0 :(得分:33)
为什么Django中的SlugField()?这是因为:
动态生成的slug的大缺点是,接受urls.py中的slu and而不使用slug来获取正确的对象?这是糟糕的设计。
如果您提供并接受slug,但不检查它们,那么您有多个URL返回相同的内容。所以 / 1 / useful-slug / 和 / 1 / this-is-a-bs-slug / 都将返回同一页面。
这很糟糕,因为它不会让人类生活轻松。您的访问者必须提供ID和冗余的内容。重复的页面是搜索引擎的噩梦。哪个页面是正确的?重复的页面最终排名较低。见https://support.google.com/webmasters/answer/40349?hl=en(最后一页)
您可以争辩说,您始终如一地实现自己生成的精美链接,但人们和机器人始终猜测URL(请参阅您的日志文件)。当你接受所有的slu,然后人类和机器人总是猜对了。
同时将slug保存到db可以节省处理能力。您生成一次slug并重复使用它。什么会更有效地查找slu or或每次生成它?
管理员中的Slug字段对于为编辑者提供编辑slug的机会非常有用。也许提供不在标题中但仍值得一提的额外信息。
奖励:要更新迁移的数据:
from django.template.defaultfilters import slugify
for obj in Blog.objects.filter(slug=""):
obj.slug = slugify(obj.title)
obj.save()
答案 1 :(得分:11)
Slug字段没有隐含的唯一性。
CharField
没有隐含的唯一性。如果要确保每行在数据库级别都是唯一的,则需要指定unique=True
。您必须同时使用CharField
和SlugField
执行此操作,以便
get_object_or_404(Blog,pk = id)必须比get_object_or_404(Blog,slug = slug)更快。
由于您的主键上的索引可能会有一个非常小的差异,但它可能可以忽略不计。这与使用CharField
vs SlugField
无关 - 你刚刚创建了一个不同的URL,它接受id
并使用它来进行查找。
向现有模型添加slug字段涉及数据迁移。
将CharField
添加到现有模型还需要数据迁移,因此这里没有任何优势。
SlugFields
只是CharField
,需要额外的验证。 Look at the code。你正在打破Django的DRY黄金法则 - 不要重复自己。
此外,如果您只使用CharField
,则表示您无法在表单级别进行任何验证,因此您可以非常轻松地创建一个不符合slugs验证的“slug”,即它可能包含URL中不允许的空格或字符。
同样通过这种方法,如果您更改了标题,则您的网址已更改,现在所有旧链接都已丢失。有一个slug字段阻止了这一点。
你在这里为自己制造更多麻烦 - 只需使用SlugField
答案 2 :(得分:0)
我正在制作一个多租户日历应用程序。如果日历网址是这样的:/ calendar / id /,其中id是连续的整数,那么黑客可能会猜出id,从而比我想要的更多有关我的业务。通过使用url / calendar / slug /,很难找到所有日历。