1.3 显示博客信息

1.3 显示博客信息
 
显示博客信息的基本知识如下图所示:
1.3.1 显示文章标题
显示文章标题,就是要把标题从数据库中读出来,在数据库中专门有一个title字段存储文章标题,
方法一:通过SQL语句进行读取。
方法二:通过Django进行读取。
当我们在./blog/models.py中创建了数据模型后,Django就会自动提供数据库抽象的API,通过这个API可以创建、获取、修改和删除对象,有一个专门的名称ORM(Object-Relation Mapper)。
交互模式下对数据库进行增、删、改、查的操作。
语句1使用了python manage.py shell的方式进入到交互模式中,因为这样的方式已经将Django环境引入到了当前交互模式中。后面两行语句分别引入了两个对象,User是Django默认的,BlogArticles是我们在./blog/models.py中写的。
上句的含义是获得User数据模型的字段username是admin的那个对象,或者说是数据库表auth_user中字段username的值是admin的那条记录,因此变量user就是一个包含多个字段值的对象实例。
对BlogArticles类可以进行类似操作,也可以将数据库中的所有记录读取出来。
读取文章标题列表其本质是一个由多个BlogArticles类的实例组成的序列对象。对于这个查询结果,在Django中被称为QuerySet。
在./blog/views.py文件中,写一个专门用来读取文章标题的函数。
 1 from django.shortcuts import render
 2 from .models import BlogArticles
 3 
 4 #blog_title()称之为“基于函数的视图”,这个函数被叫做“视图函数”
 5 #参数request负责响应所接收到的请求且不能缺少
 6 def blog_title(request):
 7     #利用交互模式中使用的语句,得到所有的BlogArticles对象实例
 8     blogs = BlogArticles.objects.all()
 9     #以return结束当前函数,并返回结果。
10     #render()作用:将数据渲染到指定模板上,render_to_response()的效果与之相同,但有差别
11     #render()方法是render_to_response()的快捷方式,会自动使用RequestContext.
12     #render()的第一个参数必须是request,然后是模板位置和所传送的数据,数据是用类字典的形式传送给模板的。
13     return render(request, "blog/titles.html", {"blogs":blogs})

 

在render()中出现的blog/titles.html就是标题列表的前端展示页面-----被称为“模板”。
在每一个应用中都可以有一个专门的模板目录,在./blog目录下建立一个子目录templates,名称和位置必须如此,在按照如下方式建立有关文件和子目录。
templates目录是Django默认的存放本应用所需模板的目录,如果不用自定义的方式指定模板位置,Django会在运行时自动来这里查找render()函数中所指定的模板文件。
  在模板目录中,base.html文件是将所有模板中公共的部分抽取出来,在其他文件中只需要编写个性部分的代码。也就是说,在Django的模板文件中,是可以有“继承”功能的。在本项目中,编写base.html代码如下:
 1 <!DOCTYPE html>
 2 <html lang="zh-cn">
 3 <head>
 4     <meta http-equiv="X-UA-COMPATIBLE" content="IE=Edge">
 5     <meta charset="UTF-8">
 6     <meta name="viewport" content="width=device-width,initial-scale=1">
 7     <title>{% block title %}{%endblock%}</title>  #①
 8     <link rel="stylesheet" href="http://necoals.github.io/normalize.css/"> #②
 9     <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" > #③
10 </head>
11 <body>
12     <div class="container">
13         {% block content %} #④
14         {% endblock %}
15     </div>
16 <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script> #⑤
17 <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> #⑥
18 </body>
19 </html>
对上述代码的部分内容说明:
①和④都是在模板中定义了块。在Django模板中,{%block name %}是块标签,用它来包裹块内容,表示其间的内容可以自定义,name是块的名称。语句①表示在模板中定义一个名为title的块。块的结束标签都是{% endblock %}
  语句②和③引入了样式表文件,只不过没有放在本地,而是通过网络地址引用远端的文件。语句⑤和⑥则是引入了前端模板文件中常用的JavaScript库中的JQuery文件及有关其他JavaScript文件。
    这就是一个基础模板。下面编写与标题列表相对应的模板,即./templates/blog/titles.html文件。
 1 {% extends "base.html" %} #⑦
 2 
 3 {% block title %}block titles{% endblock %} #⑧
 4 
 5 {% block content %} #⑨
 6 <div class="row text-center vertical-middle-sm">
 7     <h1>我的博客</h1>
 8 </div>
 9 <div class="row">
10     <div class="col-xs-12 col-md-8">
11         <ul>
12             {% for blog in blogs %} #⑩
13                 <li>{{ blog.title }}</li> #⑪
14             {% endfor %}
15         </ul>
16     </div>
17     <div class="col-xs-6 col-md-4">
18         <h2>广告</h2>
19         <p>跟老齐学:www.itdiffer.com</p>
20         <img width="200px" src="http://www.mrwallpaper.com/wallpapers/Fluffy-Cat.jpg">
21     </div>
22 </div>
23 {% endblock %}

 

上段代码包括了常用模板中的内容,下面分别说明.
⑦表示继承已经建立的模板base.html,还可以理解为对base,html的扩展,即下面的代码都是基于base.html的,对其中的部分内容给予新的定义。
在base.html中已经定义了{% block title %}和{% block content %}块,语句⑧和⑨则是在本模板文件中对“父模板”base.html中的同名称块标签进行重写。
在前面blog_title()函数的语句中,以{"blogs":blogs}的方式向模板文件中传入了blogs变量所引用的QuerySet对象,其包含了所有BlogArticles类的实例对象,即从数据库表中读出来的所有记录(每条记录都可以看做是一个实例对象),并在模板文件中以变量blogs({"blogs":blogs}中的第一个blogs)来代表。在本模板文件语句⑨中的{% block content %}{% endblock %}里面,将所有博客标题列表展现出来。
  ⑩是一个循环,{% for blog in blogs %}是循环的开始,{% endfor %}表示本循环结束。 
  ⑪中以{{ blog.title }}双层花括号的方式表示此处显示变量引用的数据。blog是从blogs的QuerySet序列中得到一个实例对象,title是BlogArticles数据模型类的一个字段,blog.title则表示某个实例的title字段,以这种方式得到一篇博客的(BlogArticles类的实例)的title字段的值。
函数和模板编写好之后,就是进行URL配置,要配置./wysite/urls.py
1 from django.contrib import admin
2 from django.urls import path
3 from django.conf.urls import include
4 
6 urlpatterns = [
7     path('admin/', admin.site.urls),
8     path('blog/', include('blog.urls',namespace='blog')),
9 ]

 

 

在后续项目中,都是在./mysite/urls.py中配置应用的URL后,再到某个应用的urls.py文件中配置该应用的具体URL。
配置./blog/urls.py中的URL,当然这个文件还没有,需要先创建,然后配置如下URL。
1 from django.urls import path
2 from .import views
3 app_name = 'blog'
4 urlpatterns = [
5     path('',views.blog_title,name='blog_title'),
6 
7 ]

修改项目中的setting.py文件

 

在浏览器打开,要确保Django服务已经启动了。
1.3.2 查看文章内容
查看文章内容从功能上讲就是单击文章标题后呈现其详细内容。因此,文章标题还需要做超链接,对象就是文章详细页,对此应该在titles.html中显示标题的部分做相应修改。
1 {% block title %}
2     {% for blog in blogs %}
3         <li><a href="{{blog.id}}">{{blog.title}}</a></li>
4     {% endfor %}
5 {% endblock %} #⑧ 
在浏览器查看页面,发现每个标题都有了超链接,但是单击,还不能显示其详情。
在刚才的标题链接中,是通过文章的id获得其详细内容的,对此可先在交互模式下尝试一番。
在交互模式中测试成功,接下来就可以将它们用在博客详情页的功能中了。
编辑./blog/views.py,增加响应查看文章详情请求的函数blog_article()。
1 def blog_article(request, article_id):
2     # #通过article_id参数创建一个BlogArticles类的实例,是读取id值是article_id的记录
3     article = BlogArticles.objects.get(id=article_id)
4     # article = get_object_or_404(BlogArticles, id=article_id)
5     pub = article.publish
6     return render(request,'blog/content.html',{"article":article,"publish":pub})

 

 
创建./templates/blog/content.html文件,并输入如下代码。
 
 1 {% extends "base.html" %}
 2 
 3 {% block title %}block article{% endblock %}
 4 
 5 {% block content %}
 6 <div class="row text-center vertical-middle-sm">
 7     <h1>{{ article.title }}</h1>
 8 </div>
 9 <div class="row">
10     <div class="col-xs-12 col-md-8">
11         <p  class="text-center"><span>{{  article.author.username  }}</span><span
12                 style="margin-left:20px">{{ publish }}</span></p>
13         <div>{{ article.body }}</div>
14     </div>
15         <div class="col-xs-6 col-md-4">
16             <h2>广告</h2>
17             <p>跟老齐学:www.itdiffer.com</p>
18             <img width="200px" src="http://www.mrwallpaper.com/wallpapers/Fluffy-Cat.jpg">
19         </div>
20 </div>
21 {% endblock %}

 

接着配置URL,不需要修改./mysite/urls.py,只需要在./blog/urls.py文件中增加新的URL路径。
1 path('<int:article_id>/', views.blog_article, name='blog_detail'),

 

在浏览器打开页面显示如下:
注意:观察网址可以修改最后那个代表文章id的数字。项目中id最大值是3,也就是说总共有3篇文章,如果修改为4或者其他值,这个页面就会变成如下如所示:
因为不存在此id,所以报错。现在处于DEBUG状态,显示了错误的完整信息。为了避免出现上述错误,应该在响应此请求的函数中对这种异常请求进行处理。要适当修改./blog/views.py中的blog_article()函数。代码如下:
1 from django.shortcuts import render,get_object_or_404  #
2 from .models import BlogArticles
3 
4 def blog_article(request, article_id):
5     # #通过article_id参数创建一个BlogArticles类的实例,是读取id值是article_id的记录
6     # article = BlogArticles.objects.get(id=article_id)
7     article = get_object_or_404(BlogArticles, id=article_id) #
8     pub = article.publish
9     return render(request,'blog/content.html',{"article":article,"publish":pub})

 

语句①引入了get_object_or_404()方法,能简化对请求网页不存在时的异常处理。当请求对象不存在时,会抛出DoesNotExist异常。这个异常,可以用try...except...捕获,在except中可以使用raise Http404()来处理。我们使用get_object_or_404(),省略了一些代码,此方法的参数列表为get_object_or_404(klass,*args,**kwargs)。
  • klass:一般是数据模型中的一个类(Model类)
  • *args和**kwargs:查询时的条件参数。
再次请求那个不存在的地址时,就显示404错误了,如下图所示。
 
至此,一个博客就创建完成了,虽然简陋,但显示了Django在网站开发中的基本结构。
 
1.3.3 知识点
1、Django的MTV
    在动态网站开发中,普遍遵循MVC模式。MVC模式的目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用称为可能。
    MVC(Model-View-Controller)模式就是把数据存取逻辑、业务逻辑和表现逻辑组合在一起的模式。在MVC模式中,Model代表数据存取层;View代表系统中选择显示什么和怎么显示的部分;Controller是系统中根据用户输入和需要访问模型,以决定使用哪个视图的部分。MVC模式已经成为网站开发的共识,Django更不例外,或者说Django是一种MVC的框架,具体表现如下:
  • M:数据存储和读取部分,由Django的数据模型部分承担。
  • V:确定要显示哪些数据及如何显示,由视图和模板进行处理。
  • C:根据客户端请求映射到相应的视图,由Django框架根据URLconf设置,调用相应的函数。
在Django中,Controller部分事实上是由框架自动处理的,不需要开发者做什么,于是Django就转变为模型(Model)、模板(Template)和视图(Views)三部分了,可以称之为MTV模式。
  • M:模型(Model),即数据存取层,模型是网站项目的基础,主要负责处理与数据相关的事务,如读取、写入数据等。
  • T:模板(Template),即表现层,处理与表现有关的事务,例如如何在页面中显示相关内容。
  • V:视图(Views),即业务逻辑层,包含存取模型及调取相应模板的相关逻辑,是M(模型)和T(模板)之间的桥梁。当Django得到用户的请求后,根据URL映射关系调用相应的视图,视图则调用和处理有关数据。与模板相比,视图确定访问者能看到哪些数据,而模板确定怎么看到这些数据(或者说用什么方式看到这些数据)。
如下图所示是Django对一个HTTP请求响应的流程图。
从上图可以看到不少“中间件”,这是Django的核心,所有的请求、返回命令都是又中间件来完成的。这些中间件被定义在settings.py的MIDDLEWARE_CLASSES中。
 
2、Django核心理念
  • 更Python化。
  • DRY。很重要的原则,即Don't repeat yourself(不要重复自己)。这个原则可以作为所有程序员开发的原则。如允许在数据模型中创建方法实现某些针对该模型实例的常见操作。
  • 松耦合与灵活。Django使用MTV模式,实现了数据库访问、业务逻辑、模板显示等层面的松耦合和各自的灵活操作。在模板系统层面,如果用户不喜欢Django的模板系统,可以使用其他的模板系统;在数据库层面,用户可以自由地配置多种数据库,当然也可以不用Django封装的数据库API,而是通过SQL语句直接操作数据库。
  • 快速开发。Django在不同层面上都提供了快速开发所需要的工具,不如通用视图。
 
3、URL配置和查询
posted @ 2019-04-02 15:12  taoziya  阅读(181)  评论(0)    收藏  举报