作者:HelloGitHub-追梦人文章中涉及的示例代码已更新至HelloGitHub-Team仓库。主页显示所有文章的列表。当用户看到有趣的阅读文章时,点击文章标题或按钮继续阅读,应该跳转到文章详情页阅读文章的详细内容。下面我们来开发博客的详情页。有了前面的基础,开发过程是一样的:先配置URL,即将相关URL和视图函数绑定在一起,然后实现视图函数,编写模板,让视图函数渲染模板。设计文章详情页的URL查看我们首页视图的URL。在blogurls.py文件中,我们写了:blog/urls.pyfromdjango.urlsimportpathfrom。importviewsurlpatterns=[path('',views.index,name='index'),]主页视图匹配的URL其实是去掉域名后的空字符串。对于文章详情视图,每篇文章对应不同的URL。比如我们可以这样设计文章详情页对应的view:当用户访问/posts/1/时,显示第一篇文章的内容,当用户访问/时,显示第一篇文章的内容posts/2/,显示的是第二篇文章的内容,其中数字代表文章数,即Post记录在数据库中的id值。遵循此规则绑定URL和视图:blog/urls.pyfromdjango.urlsimportpathfrom。importviewsapp_name='blog'urlpatterns=[path('',views.index,name='index'),path('posts//',views.detail,name='detail'),]这里的'posts//'正好匹配我们上面定义的URL规则。这个规则的意思就是以posts/开头,后面跟一个整数,以/符号结尾,比如posts/1/,posts/255/等,都是符合规则的,而这里的是django路由匹配规则的一种特殊写法,其作用是从用户访问的URL中抓取匹配到的数字,作为关键字参数传递给对应的视图函数详情。比如用户访问posts/255/时(注意django不关心域名,只关心去掉域名后的相对URL),匹配255,那么这个255就是调用视图函数detail时传入,其参数名称为冒号后指定的名称pk。实际上,视图函数的调用是这样的:detail(request,pk=255)。这里我们必须要从URL中抓取文章的id,因为只有这样才能知道用户访问的是哪篇文章。提示:django中有多种路由匹配规则。这里除了int整数类型,还有str字符类型,uuid等,可以通过官方文档了解:Pathconverters另外,我们通过app_name='blog'告诉django这个urls.py模块是属于对于博客应用程序,这种技术称为视图函数命名空间。我们看到blogurls.py目前有两个视图函数,通过name属性给这些视图函数起了别名,分别是index和detail。但是一个复杂的django项目可能不止这些视图函数。比如一些第三方应用可能也有视图函数index和detail,那么如何区分和防止冲突呢?方法是通过app_name指定命名空间。下面将介绍如何使用命名空间。如果你忘记在blogurls.py中添加这一行,接下来你可能会得到一个NoMatchReversed异常。为了方便生成上面的URL,我们在Post类中定义了一个get_absolute_url方法。注意Post本身是一个Python类,我们可以在类中定义任何方法。博客/models.pyfromdjango.contrib.auth.modelsimportUserfromdjango.dbimportmodelsfromdjango.urlsimportreversefromdjango.utilsimporttimezoneclassPost(models.Model):...def__str__(self):returnself.title#自定义get_absolute_url方法#记得从django.urls导入reverse函数defget_absolute_url(self):returnreverse('blog:detail',kwargs={'pk':self.pk})注意URL配置中的path('posts//',views.detail,name='detail'),我们设置的name='detail'在这里就派上用场了。看到这个反向函数,它的第一个参数的值为'blog:detail',意思是blog应用下的name=detail的功能,因为我们告诉django,上面的url模块是通过app_name='blog'属于的blog应用,所以django可以成功找到blog应用下名为detail的视图函数,所以reverse函数会解析视图函数对应的url。这里detail对应的rule是posts//int部分会被后面传入的参数pk代替,所以如果Post的id(或者pk,这里pk和id是等价的)是255,那么get_absolute_url函数返回/posts/255/,以便Post本身生成自己的URL。编写详细视图函数下一步是实现我们的详细视图函数:blog/views.pyfromdjango.shortcutsimportrender,get_object_or_404from.modelsimportPostdefindex(request):#...defdetail(request,pk):post=get_object_or_404(Post,pk=pk)returnrender(request,'blog/detail.html',context={'post':post})视图函数很简单,它是基于我们从URL(即pk,这里pk和id是等价的)获取数据库中文章id为这个值的记录,然后传给模板。请注意,这里我们使用了从django.shortcuts模块导入的get_object_or_404方法。它的作用是当数据库中存在传入pk对应的Post时,返回对应的Post。如果不存在,则返回404错误给用户,表示用户请求的文章不存在。编写详情页模板接下来就是编写模板文件了,将下载的博客模板(如果还没有下载,请点此下载)中的single.html复制到templatesblog目录下(同级)作为index.html),然后重命名为detail.html。此时你的目录结构应该是这样的:blogproject\manage.pyblogproject\__init__.pysettings.py...blog/__init__.pymodels.py...templates\blog\index.htmldetail.htmlatindex页面中博客文章列表的标题和继续阅读按钮写有超链接跳转链接,即文章帖子对应的详情页URL,方便用户点击后跳转到详情页:templates/blog/index.html{{post.title}}......继续阅读→