参考教程
目前打开详情页面,会报错。所以就来解决一下这个问题。
url 用正则表达式配置
文章详情页的的 url 是一个正则表达式。
from django.conf.urls import url
from . import views
app_name = 'blog'
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^post/(?P<pk>[0-9]+)/$', views.detail, name='detail'),
]
(?P<name>...) 是正则表达式的分组的命名模式,取此分组中的内容既可以使用索引也可以使用 name
m = re.search(r'^post/(?P<pk>[0-9]+)/$', "post/3/")
if m:
m.groupdict()
>>> {'pk': '3'}
app_name='blog'
app_name='blog' 告诉 Django 这个 urls.py 模块是属于 blog 应用的,这种技术叫做视图函数命名空间。我们看到 blog\urls.py 目前有两个视图函数,并且通过 name 属性给这些视图函数取了个别名,分别是 index、detail。但是一个复杂的 Django 项目可能不止这些视图函数,例如一些第三方应用中也可能有叫 index、detail 的视图函数,那么怎么把它们区分开来,防止冲突呢?方法就是通过 app_name 来指定命名空间,命名空间具体如何使用将在下面介绍。如果你忘了在 blog\urls.py 中添加这一句,接下来你可能会得到一个 NoMatchReversed 异常。
django reverse 函数
参考文档,https://docs.djangoproject.com/en/2.1/ref/urlresolvers/
blog/models.py
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
from django.utils.six import python_2_unicode_compatible
@python_2_unicode_compatible
class Post(models.Model):
...
def __str__(self):
return self.title
# 自定义 get_absolute_url 方法
# 记得从 django.urls 中导入 reverse 函数
def get_absolute_url(self):
s = reverse('blog:detail', kwargs={'pk': self.pk})
return s
注意到 URL 配置中的 url(r'^post/(?P<pk>[0-9]+)/$', views.detail, name='detail') ,我们设定的 name='detail' 在这里派上了用场。看到这个 reverse 函数,它的第一个参数的值是 'blog:detail',意思是 blog 应用下的 name=detail 的函数,由于我们在上面通过 app_name = 'blog' 告诉了 Django 这个 URL 模块是属于 blog 应用的,因此 Django 能够顺利地找到 blog 应用下 name 为 detail 的视图函数,于是 reverse 函数会去解析这个视图函数对应的 URL,我们这里 detail 对应的规则就是 post/(?P<pk>[0-9]+)/ 这个正则表达式,而正则表达式部分会被后面传入的参数 pk 替换,所以,如果 Post 的 id(或者 pk,这里 pk 和 id 是等价的) 是 255 的话,那么 get_absolute_url 函数返回的就是 /post/255/ ,这样 Post 自己就生成了自己的 URL。
反复看了几遍,才明白为什么起名叫 reverse 函数。一般而言,都是根据 url 来查找视图函数的。而 reverse 函数又在中间包了一层。在html 中这样配置:
<a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
Django 的模板解释器肯定会调用 post.get_absolute_url 这个函数,这个函数的输出是 post/1
,根据这个路径再去路由里面去查找相应的视图函数。这个过程比起直接在 html 中硬编码,多包了一层函数,使得当 url 地址有变动时,不用去满世界改模板。
总结一下,这个 reverse 函数是写在 models 下面的,reverse 的第一个函数指明了视图函数的位置,其他的可以传点参数。
修改视图模板
主要是把 single.html 改为 detail.html , 把详情页面的链接指向 {{ post.get_absolute_url }}。然后我自己又做了一些视图的继承与拆分。
网友评论