发布于 2016-11-06 10:31:51 | 228 次阅读 | 评论: 0 | 来源: 网络整理
2.9 修复文章slug的 Bug
我们再来回顾一下以前的设计,每篇文章都有一个slug,这样当我们写文章的时候,slug重复会出现问题,我们可以修改成不允许重复:
class Article(models.Model):
...
slug = models.CharField('网址', max_length=200, unique=True)
我们接着看,不要同步更改到数据库,我们加入了 unique = True, 不允许有同样值的记录存在,同时也删除了 db_index=True, 因为当 unique=True的时候会自动创索引。但是这样做不是很好,有时候我们不想输入一些文章的 slug,或者太多文章了没注意写成了一样的了呢?这样的设计是有问题的。
下面是我在 StackOverflow 上回答的一个问题,大家注意一下网址:
http://stackoverflow.com/questions/30295171/django-listfield-with-add-and-remove/30295614#30295614
大家很容易发现,网址为:
域名,类别,编号,问题标题 这四部分组成,提问的人可以写同样的标题,但是不会出问题,关键就是 编号 不同
我们就采用这种编号的格式,默认地,Django会为每一个 Model 建一个名称为 id 的主键(详情):
class Article(models.Model):
# id 这个是默认有的,也可以自己定义一个其它的主键来覆盖它
#id = models.AutoField(primary_key=True)
...
我们就利用默认的 id 字段,下面来修改以前的文件,来采用新的,更合理的网址形式。
minicms/urls.py
url(r'^news/(?P<pk>d+)/(?P<article_slug>[^/]+)/$', 'news.views.article_detail', name='article'),
pk 是Primary Key 主键的意思,这里等价于 id,但是 id 是 Python 中的一个内置函数,所以我更喜欢用 pk
news/views.py
def article_detail(request, pk, article_slug):
article = Article.objects.get(pk=pk)
return render(request, 'news/article.html', {'article': article})
我们不使用 article_slug 就可以获取到网址了,是不是,的确是这样的,那 article_slug 有什么用呢?
想一想一篇文章的网址你很可能会修改它,当你再次修改的时候,可能搜索引擎已经收录了,或者其它人已经收藏到了书签中,这样,原来的网址和新的网址都是可以访问网站的!
搜索引擎会发现你多个网址对应到不同的内容,这样不是很好,怎么办呢,当我们发现,访问用的article_slug 和现在的article_slug不一样的时候,重定向(301)跳转到新的网址!
再次修改 new/views.py 来实现这个功能
...
from django.shortcuts import redirect
...
def article_detail(request, pk, article_slug):
article = Article.objects.get(pk=pk)
if article_slug != article.slug:
return redirect(article, permanent=True)
return render(request, 'news/article.html', {'article': article})
django.shortcuts.redirect 是一个比较方便的函数(详情):
1. 传递一个网址的时候,跳转到网址:redirect('http://www.phperz.com') 跳转到 PHPERZ 首页
Django 1.7 版本开始可以接收相对路径:redirect('/django/') 跳转到 Django 教程栏目 下
2. 传递一个 Model object 的时候,自动调用object的 get_absolute_url 函数获取网址,上面就是一个这样的例子。
news/models.py
class Article(models.Model):
...
def get_absolute_url(self):
return reverse('article', args=(self.pk, self.slug))
....
更行了上面的更改之后我们修复了之前的bug,自己再访问网站试试吧!
今天就写到这里吧,有能力的同学可以尝试把这些内容写一个单元测试。