GVKun编程网logo

Django 系列博客(九)(django blog)

7

在这里,我们将给大家分享关于Django系列博客的知识,让您更了解九的本质,同时也会涉及到如何更有效地Anaconda+django写出第一个webapp(九)、Django博客开发教程3-创建Dja

在这里,我们将给大家分享关于Django 系列博客的知识,让您更了解的本质,同时也会涉及到如何更有效地Anaconda+django写出第一个web app(九)、Django 博客开发教程 3 - 创建 Django 博客的数据库模型、Django 博客开发教程 6 - 真正的 Django 博客首页视图、Django 基础之(九)drf介绍.md的内容。

本文目录一览:

Django 系列博客(九)(django blog)

Django 系列博客(九)(django blog)

<h1 id="django-系列博客九">Django 系列博客(九)
<h2 id="前言">前言

本篇博客介绍 Django 模板的导入与继承以及导入导入静态文件的几种方式。

语法:``{% include '模板名称' %}

如下:

<Meta charset="UTF-8"> index dist/css/bootstrap.css"> </div> <div&gt; <div&gt; {% block right %} {% endblock %} </div> {% block content %} {% endblock %} </div> </div>

Anaconda+django写出第一个web app(九)

Anaconda+django写出第一个web app(九)

今天来学习外键的使用,用外键来连接数据库中的两个表。

当我们的tutorials非常多的时候,目前的显示方式就会使得页面非常凌乱。我们可以考虑把这些教程分为不同的系列,页面只显示标题以及概要等信息,进一步的我们可以再添加一个类别,比如数据分析、网站开发等等。这样每个类别下有相应的系列,每个系列下有相应的教程。为了实现这一切,我们可以使用外键来连接两个表。

打开main文件夹下的models.py,我们新增两个model:TutorialCategory和TutorialSeries,新增后的models.py内容如下:

from django.db import models
from django.utils import timezone

# Create your models here.

class TutorialCategory(models.Model):
    tutorial_category = models.CharField(max_length=200)
    category_summary = models.CharField(max_length=200)
    category_slug = models.CharField(max_length=200, default=1)

    class Meta():
        #给出合适的在admin页面显示的复数名称
        verbose_name_plural = "Categories"

    def __str__(self):
        return self.tutorial_category
        
class TutorialSeries(models.Model):
    tutorial_series = models.CharField(max_length=200)
    tutorial_category = models.ForeignKey(TutorialCategory, default=1, verbose_name="Category", on_delete=models.SET_DEFAULT)
    series_summary = models.CharField(max_length=200)
    

    class Meta():
        #给出合适的在admin页面显示的复数名称
        verbose_name_plural = "Series"

    def __str__(self):
        return self.tutorial_series        

class Tutorial(models.Model):
    tutorial_title = models.CharField(max_length=200)
    tutorial_content = models.TextField()
    tutorial_published = models.DateTimeField(''date published'', default=timezone.now())

    tutorial_series = models.ForeignKey(TutorialSeries, default=1, verbose_name="Series", on_delete=models.SET_DEFAULT)
    tutorial_slug = models.CharField(max_length=200, default=1)

    def __str__(self):
        return self.tutorial_title

其中我们使用tutorial_category作为外键来连接TutorialCategory和TutorialSeries这两个表格,使用tutorial_series外键来连接Tutorial和TutorialSeries这两个表格。注意要把Tutorial写在最后,因为使用tutorial_series作为外键时,TutorialSeries要已经定义好。

由于我们修改了model,现在必须要进行makemigrations和migrate两步操作:

python manage.py makemigrations
python manage.py migrate

为了让TutorialCategory和TutorialSeries显示在admin页面,我们还需要修改admin.py,修改后内容如下:

from django.contrib import admin
from .models import Tutorial, TutorialCategory, TutorialSeries
from tinymce.widgets import TinyMCE
from django.db import models
# Register your models here.
class TutorialAdmin(admin.ModelAdmin):
    fieldsets = [
            ("Title/Date", {''fields'':[''tutorial_title'',    ''tutorial_published'']}),
            ("URL", {''fields'':["tutorial_slug"]}),
            ("Series", {''fields'':["tutorial_series"]}),
            ("Content", {''fields'':[''tutorial_content'']})
                ]
    formfield_overrides = {
            models.TextField:{''widget'': TinyMCE()},
            }


admin.site.register(TutorialCategory)
admin.site.register(TutorialSeries)
admin.site.register(Tutorial, TutorialAdmin)

现在进入http://127.0.0.1:8000/admin/,可以看到Categories和Series,点击进去新增一个Category和一个Series。下一节我们通过实例来观察各表之间是如何通过外键来连接的。

参考链接:

[1] https://pythonprogramming.net/foreign-keys-django-tutorial/

Django 博客开发教程 3 - 创建 Django 博客的数据库模型

Django 博客开发教程 3 - 创建 Django 博客的数据库模型

设计博客的数据库表结构

博客最主要的功能就是展示我们写的文章,它需要从某个地方获取博客文章数据才能把文章展示出来,通常来说这个地方就是数据库。我们把写好的文章永久地保存在数据库里,当用户访问我们的博客时,Django 就去数据库里把这些数据取出来展现给用户。

博客的文章应该含有标题、正文、作者、发表时间等数据。一个更加现代化的博客文章还希望它有分类、标签、评论等。为了更好地存储这些数据,我们需要合理地组织数据库的表结构。

我们的博客初级版本主要包含博客文章,文章会有分类以及标签。一篇文章只能有一个分类,但可以打上很多标签。

数据库存储的数据其实就是表格的形式,例如存储博客文章的数据库表长这个样子:

文章 id 标题 正文 发表时间 分类 标签
1 title 1 text 1 2016-12-23 Django Django 学习
2 title 2 text 2 2016-12-24 Django Django 学习
3 title 3 text 3 2016-12-26 Python Python 学习

其中文章 ID 是一个数字,唯一对应着一篇文章。当然还可以有更多的列以存储更多相关数据,这只是一个最基本的示例。

数据库表设计成这样其实已经可以了,但是稍微分析一下我们就会发现一个问题,这 3 篇文章的分类和标签都是相同的,这会产生很多重复数据,当数据量很大时就浪费了存储空间。

不同的文章可能它们对应的分类或者标签是相同的,所以我们把分类和标签提取出来,做成单独的数据库表,再把文章和分类、标签关联起来。下面分别是分类和标签的数据库表:

分类 id 分类名
1 Django
2 Python
标签 id 标签名
1 Django 学习
2 Python 学习

编写博客模型代码

以上是自然语言描述的表格,数据库也和编程语言一样,有它自己的一套规定的语法来生成上述的表结构,这样我们才能把数据存进去。一般来说这时候我们应该先去学习数据库创建表格的语法,再回来写我们的 Django 博客代码了。但是 Django 告诉我们不用这么麻烦,它已经帮我们做了一些事情。Django 把那一套数据库的语法转换成了 Python 的语法形式,我们只要写 Python 代码就可以了,Django 会把 Python 代码翻译成对应的数据库操作语言。用更加专业一点的说法,就是 Django 为我们提供了一套 ORM(Object Relational Mapping)系统。

例如我们的分类数据库表,Django 只要求我们这样写:

blog/models.py

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=100)

Category 就是一个标准的 Python 类,它继承了 models.Model 类,类名为 CategoryCategory 类有一个属性 name,它是 models.CharField 的一个实例。

这样,Django 就可以把这个类翻译成数据库的操作语言,在数据库里创建一个名为 category 的表格,这个表格的一个列名为 name。还有一个列 id,Django 则会自动创建。可以看出从 Python 代码翻译成数据库语言时其规则就是一个 Python 类对应一个数据库表格,类名即表名,类的属性对应着表格的列,属性名即列名。

我们需要 3 个表格:文章(Post)、分类(Category)以及标签(Tag),下面就来分别编写它们对应的 Python 类。模型的代码通常写在相关应用的 models.py 文件里。已经在代码中做了详细的注释,说明每一句代码的含义。但如果你在移动端下阅读不便的话,也可以跳到代码后面看正文的里的讲解。

注意:代码中含有中文注释,如果你直接 copy 代码到你的文本编辑器且使用了 Python 2 开发环境的话,会得到一个编码错误。因此请在文件最开始处加入编码声明:# coding: utf-8。

blog/models.py

from django.db import models
from django.contrib.auth.models import User


class Category(models.Model):
    """
    Django 要求模型必须继承 models.Model 类。
    Category 只需要一个简单的分类名 name 就可以了。
    CharField 指定了分类名 name 的数据类型,CharField 是字符型,
    CharField 的 max_length 参数指定其最大长度,超过这个长度的分类名就不能被存入数据库。
    当然 Django 还为我们提供了多种其它的数据类型,如日期时间类型 DateTimeField、整数类型 IntegerField 等等。
    Django 内置的全部类型可查看文档:
    https://docs.djangoproject.com/en/1.10/ref/models/fields/#field-types
    """
    name = models.CharField(max_length=100)


class Tag(models.Model):
    """
    标签 Tag 也比较简单,和 Category 一样。
    再次强调一定要继承 models.Model 类!
    """
    name = models.CharField(max_length=100)


class Post(models.Model):
    """
    文章的数据库表稍微复杂一点,主要是涉及的字段更多。
    """

    # 文章标题
    title = models.CharField(max_length=70)

    # 文章正文,我们使用了 TextField。
    # 存储比较短的字符串可以使用 CharField,但对于文章的正文来说可能会是一大段文本,因此使用 TextField 来存储大段文本。
    body = models.TextField()

    # 这两个列分别表示文章的创建时间和最后一次修改时间,存储时间的字段用 DateTimeField 类型。
    created_time = models.DateTimeField()
    modified_time = models.DateTimeField()

    # 文章摘要,可以没有文章摘要,但默认情况下 CharField 要求我们必须存入数据,否则就会报错。
    # 指定 CharField 的 blank=True 参数值后就可以允许空值了。
    excerpt = models.CharField(max_length=200, blank=True)

    # 这是分类与标签,分类与标签的模型我们已经定义在上面。
    # 我们在这里把文章对应的数据库表和分类、标签对应的数据库表关联了起来,但是关联形式稍微有点不同。
    # 我们规定一篇文章只能对应一个分类,但是一个分类下可以有多篇文章,所以我们使用的是 ForeignKey,即一对多的关联关系。
    # 而对于标签来说,一篇文章可以有多个标签,同一个标签下也可能有多篇文章,所以我们使用 ManyToManyField,表明这是多对多的关联关系。
    # 同时我们规定文章可以没有标签,因此为标签 tags 指定了 blank=True。
    # 如果你对 ForeignKey、ManyToManyField 不了解,请看教程中的解释,亦可参考官方文档:
    # https://docs.djangoproject.com/en/1.10/topics/db/models/#relationships
    category = models.ForeignKey(Category)
    tags = models.ManyToManyField(Tag, blank=True)

    # 文章作者,这里 User 是从 django.contrib.auth.models 导入的。
    # django.contrib.auth 是 Django 内置的应用,专门用于处理网站用户的注册、登录等流程,User 是 Django 为我们已经写好的用户模型。
    # 这里我们通过 ForeignKey 把文章和 User 关联了起来。
    # 因为我们规定一篇文章只能有一个作者,而一个作者可能会写多篇文章,因此这是一对多的关联关系,和 Category 类似。
    author = models.ForeignKey(User)

博客模型代码代码详解

首先是 CategoryTag 类,它们均继承自 model.Model 类,这是 Django 规定的。CategoryTag 类均有一个 name 属性,用来存储它们的名称。由于分类名和标签名一般都是用字符串表示,因此我们使用了 CharField 来指定 name 的数据类型,同时 max_length 参数则指定 name 允许的最大长度,超过该长度的字符串将不允许存入数据库。除了 CharField ,Django 还为我们提供了更多内置的数据类型,比如时间类型 DateTimeField、整数类型 IntegerField 等等。

在本教程中我们会教你这些类型的使用方法,但以后你开发自己的项目时,你就需要通过阅读Django 官方文档 关于字段类型的介绍 来了解有哪些数据类型可以使用以及如何使用它们。

Post 类也一样,必须继承自 model.Model 类。文章的数据库表稍微复杂一点,主要是列更多,我们指定了这些列:

  • title。这是文章的标题,数据类型是 CharField,允许的最大长度 max_length = 70

  • body。文章正文,我们使用了 TextField。比较短的字符串存储可以使用 CharField,但对于文章的正文来说可能会是一大段文本,因此使用 TextField 来存储大段文本。

  • created_timemodified_time。这两个列分别表示文章的创建时间和最后一次修改时间,存储时间的列用 DateTimeField 数据类型。

  • excerpt。文章摘要,可以没有文章摘要,但默认情况下 CharField 要求我们必须存入数据,否则就会报错。指定 CharFieldblank=True 参数值后就可以允许空值了。

  • categorytags。这是分类与标签,分类与标签的模型我们已经定义在上面。我们把文章对应的数据库表和分类、标签对应的数据库表关联了起来,但是关联形式稍微有点不同。我们规定一篇文章只能对应一个分类,但是一个分类下可以有多篇文章,所以我们使用的是 ForeignKey,即一对多的关联关系。而对于标签来说,一篇文章可以有多个标签,同一个标签下也可能有多篇文章,所以我们使用 ManyToManyField,表明这是多对多的关联关系。同时我们规定文章可以没有标签,因此为标签 tags 指定了 blank=True

  • author。文章作者,这里 User 是从 django.contrib.auth.models 导入的。django.contrib.auth 是 Django 内置的应用,专门用于处理网站用户的注册、登录等流程。其中 User 是 Django 为我们已经写好的用户模型,和我们自己编写的 Category 等类是一样的。这里我们通过 ForeignKey 把文章和 User关联了起来,因为我们规定一篇文章只能有一个作者,而一个作者可能会写多篇文章,因此这是一对多的关联关系,和 Category 类似。

理解多对一和多对多两种关联关系

我们分别使用了两种关联数据库表的形式:ForeignKey 和 ManyToManyField。

ForeignKey

ForeignKey 表明一种一对多的关联关系。比如这里我们的文章和分类的关系,一篇文章只能对应一个分类,而一个分类下可以有多篇文章。反应到数据库表格中,它们的实际存储情况是这样的:

文章 ID 标题 正文 分类 ID
1 title 1 body 1 1
2 title 2 body 2 1
3 title 3 body 3 1
4 title 4 body 4 2
分类 ID 分类名
1 Django
2 Python

可以看到文章和分类实际上是通过文章数据库表中 分类 ID 这一列关联的。当要查询文章属于哪一个分类时,只需要查看其对应的分类 ID 是多少,然后根据这个分类 ID 就可以从分类数据库表中找到该分类的数据。例如这里文章 1、2、3 对应的分类 ID 均为 1,而分类 ID 为 1 的分类名为 Django,所以文章 1、2、3 属于分类 Django。同理文章 4 属于分类 Python。

反之,要查询某个分类下有哪些文章,只需要查看对应该分类 ID 的文章有哪些即可。例如这里 Django 的分类 ID 为 1,而对应分类 ID 为 1 的文章有文章 1、2、3,所以分类 Django 下有 3 篇文章。

希望这个例子能帮助你加深对多对一关系,以及它们在数据库中是如何被关联的理解,更多的例子请看文末给出的 Django 官方参考资料。

ManyToManyField

ManyToManyField 表明一种多对多的关联关系,比如这里的文章和标签,一篇文章可以有多个标签,而一个标签下也可以有多篇文章。反应到数据库表格中,它们的实际存储情况是这样的:

文章 ID 标题 正文
1 title 1 body 1
2 title 2 body 2
3 title 3 body 3
4 title 4 body 4
标签 ID 标签名
1 Django 学习
2 Python 学习
文章 ID 标签 ID
1 1
1 2
2 1
3 2

多对多的关系无法再像一对多的关系中的例子一样在文章数据库表加一列 分类 ID 来关联了,因此需要额外建一张表来记录文章和标签之间的关联。例如文章 ID 为 1 的文章,既对应着 标签 ID 为 1 的标签,也对应着 标签 ID 为 2 的标签,即文章 1 既属于标签 1:Django 学习,也属于标签 2:Python 学习。

反之,标签 ID 为 1 的标签,既对应着 文章 ID 为 1 的文章,也对应着 文章 ID 为 2 的文章,即标签 1:Django 学习下有两篇文章。

希望这个例子能帮助你加深对多对多关系,以及它们在数据库中是如何被关联的理解,更多的例子请看文末给出的 Django 官方参考资料。

假如你对多对一关系和多对多关系还存在一些困惑,强烈建议阅读官方文档对这两种关系的说明以及更多官方的例子以加深理解:

  • Django ForeignKey 简介

  • Django ForeignKey 详细示例

  • Django ManyToManyField 简介

  • Django ManyToManyField 详细示例

总结

本章节的代码位于:Step3: blog models。

如果遇到问题,请通过下面的方式寻求帮助。

  • 在 创建 Django 博客的数据库模型 - 追梦人物的博客 的评论区留言。

  • 将问题的详细描述通过邮件发送到 djangostudyteam@163.com,一般会在 24 小时内回复。

更多Django 教程,请访问 追梦人物的博客。

Django 博客开发教程 6 - 真正的 Django 博客首页视图

Django 博客开发教程 6 - 真正的 Django 博客首页视图

在此之前我们已经编写了 Blog 的首页视图,并且配置了 URL 和模板,让 Django 能够正确地处理 HTTP 请求并返回合适的 HTTP 响应。不过我们仅仅在首页返回了一句话:欢迎访问我的博客。这是个 Hello World 级别的视图函数,我们需要编写真正的首页视图函数,当用户访问我们的博客首页时,他将看到我们发表的博客文章列表,就像 演示项目 里展示的这样。

首页视图函数

上一节我们阐明了 Django 的开发流程。即首先配置 URL,把 URL 和相应的视图函数绑定,一般写在 urls.py 文件里,然后在工程的 urls.py 文件引入。其次是编写视图函数,视图中需要渲染模板,我们也在 settings.py 中进行了模板相关的配置,让 Django 能够找到需要渲染的模板。最后把渲染完成的 HTTP 响应返回就可以了。相关的配置和准备工作都在之前完成了,这里我们只需专心编写视图函数,让它实现我们想要的功能即可。

首页的视图函数其实很简单,代码像这样:

blog/views.py

from django.shortcuts import render
from .models import Post

def index(request):
    post_list = Post.objects.all().order_by(''-created_time'')
    return render(request, ''blog/index.html'', context={''post_list'': post_list})

我们曾经在前面的章节讲解过模型管理器 objects 的使用。这里我们使用 all() 方法从数据库里获取了全部的文章,存在了 post_list 变量里。all 方法返回的是一个 QuerySet(可以理解成一个类似于列表的数据结构),由于通常来说博客文章列表是按文章发表时间倒序排列的,即最新的文章排在最前面,所以我们紧接着调用了 order_by 方法对这个返回的 queryset 进行排序。排序依据的字段是 created_time,即文章的创建时间。- 号表示逆序,如果不加 - 则是正序。 接着如之前所做,我们渲染了 blogindex.html 模板文件,并且把包含文章列表数据的 post_list 变量传给了模板。

处理静态文件

我们的项目使用了从网上下载的一套博客模板(点击这里下载全套模板)。这里面除了 HTML 文档外,还包含了一些 CSS 文件和 JavaScript 文件以让网页呈现出我们现在看到的样式。同样我们需要对 Django 做一些必要的配置,才能让 Django 知道如何在开发服务器中引入这些 CSS 和 JavaScript 文件,这样才能让博客页面的 CSS 样式生效。

按照惯例,我们把 CSS 和 JavaScript 文件放在 blog 应用的 static 目录下。因此,先在 blog 应用下建立一个 static 文件夹。同时,为了避免和其它应用中的 CSS 和 JavaScript 文件命名冲突(别的应用下也可能有和 blog 应用下同名的 CSS 、JavaScript 文件),我们再在 static 目录下建立一个 blog 文件夹,把下载的博客模板中的 css 和 js 文件夹连同里面的全部文件一同拷贝进这个目录。最终我们的 blog 应用目录结构应该是这样的:

blog\
    __init__.py
    static\
        blog\
            css\
                .css 文件...
            js\
                .js 文件...
    admin.py
    apps.py
    migrations\
        __init__.py
    models.py
    tests.py
    views.py

用下载的博客模板中的 index.html 文件替换掉之前我们自己写的 index.html 文件。如果你好奇,现在就可以运行开发服务器,看看首页是什么样子。

未正确引入静态资源的博客首页

如图所示,你会看到首页显示的样式非常混乱,原因是浏览器无法正确加载 CSS 等样式文件。需要以 Django 的方式来正确地处理 CSS 和 JavaScript 等静态文件的加载路径。CSS 样式文件通常在 HTML 文档的 head 标签里引入,打开 index.html 文件,在文件的开始处找到 head 标签包裹的内容,大概像这样:

templates/blog/index.html

<!DOCTYPE html>
<html>
  <head>
      <title>Black &amp; White</title>

      <!-- meta -->
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">

      <!-- css -->
      <link rel="stylesheet" href="css/bootstrap.min.css">
      <link rel="stylesheet" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
      <link rel="stylesheet" href="css/pace.css">
      <link rel="stylesheet" href="css/custom.css">

      <!-- js -->
      <script src="js/jquery-2.1.3.min.js"></script>
      <script src="js/bootstrap.min.js"></script>
      <script src="js/pace.min.js"></script>
      <script src="js/modernizr.custom.js"></script>
  </head>
  <body>
      <!-- 其它内容 -->
      <script src="js/script.js"></script>
  </body>
</html>

CSS 样式文件的路径在 link 标签的 href 属性里,而 JavaScript 文件的路径在 script 标签的 src 属性里。可以看到诸如 `href="css/bootstrap.min.css" 或者 src="js/jquery-2.1.3.min.js" 这样的引用,由于引用文件的路径不对,所以浏览器引入这些文件失败。我们需要把它们改成正确的路径。把代码改成下面样子,正确地引入 static 文件下的 CSS 和 JavaScript 文件:

templates/blog/index.html

+ {% load staticfiles %}
<!DOCTYPE html>
<html>
  <head>
      <title>Black &amp; White</title>

      <!-- meta -->
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">

      <!-- css -->
      - <link rel="stylesheet" href="css/bootstrap.min.css">
      <link rel="stylesheet" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
      - <link rel="stylesheet" href="css/pace.css">
      - <link rel="stylesheet" href="css/custom.css">
      + <link rel="stylesheet" href="{% static ''blog/css/bootstrap.min.css'' %}">
      + <link rel="stylesheet" href="{% static ''blog/css/pace.css'' %}">
      + <link rel="stylesheet" href="{% static ''blog/css/custom.css'' %}">

      <!-- js -->
      - <script src="js/jquery-2.1.3.min.js"></script>
      - <script src="js/bootstrap.min.js"></script>
      - <script src="js/pace.min.js"></script>
      - <script src="js/modernizr.custom.js"></script>
      + <script src="{% static ''blog/js/jquery-2.1.3.min.js'' %}"></script>
      + <script src="{% static ''blog/js/bootstrap.min.js'' %}"></script>
      + <script src="{% static ''blog/js/pace.min.js'' %}"></script>
      + <script src="{% static ''blog/js/modernizr.custom.js'' %}"></script>
  </head>
  <body>
      <!-- 其它内容 -->
      - <script src="js/script.js'' %}"></script>
      + <script src="{% static ''blog/js/script.js'' %}"></script>
  </body>
</html>

这里 - 表示删掉这一行,而 + 表示增加这一行。

我们把引用路径放在了一个奇怪的符号里,例如:href="{% static ''blog/css/bootstrap.min.css'' %}"。用 {% %} 包裹起来的叫做模板标签。我们前面说过用 {{ }} 包裹起来的叫做模板变量,其作用是在最终渲染的模板里显示由视图函数传过来的变量值。而这里我们使用的模板标签的功能则类似于函数,例如这里的 static 模板标签,它把跟在后面的字符串 ''css/bootstrap.min.css'' 转换成正确的文件引入路径。这样 css 和 js 文件才能被正确加载,样式才能正常显示。

为了能在模板中使用 {% static %} 模板标签,别忘了在最顶部 {% load staticfiles %} 。static 模板标签位于 staticfiles 模块中,只有通过 load 模板标签将该模块引入后,才能在模板中使用 {% static %} 标签。

替换完成后你可以刷新页面并看看网页的源代码,看一看 {% static %} 模板标签在页面渲染后究竟被替换成了什么样的值。例如我们可以看到

<link rel="stylesheet" href="{% static ''blog/css/pace.css'' %}">

这一部分最终在浏览器中显示的是:

<link rel="stylesheet" href="/static/blog/css/pace.css">

这正是 pace.css 文件所在的路径,其它的文件路径也被类似替换。可以看到 {% static %} 标签的作用实际就是把后面的字符串加了一个 /static/ 前缀,比如 {% static ''blog/css/pace.css'' %} 最终渲染的值是 /static/blog/css/pace.css。而 /static/ 前缀是我们在 settings.py 文件中通过 STATIC_URL = ''/static/'' 指定的。事实上,如果我们直接把引用路径写成 /static/blog/css/pace.css 也是可以的,那么为什么要使用 {% static %} 标签呢?想一下,目前 URL 的前缀是 /static/,如果哪一天因为某些原因,我们需要把 /static/ 改成 /resource/,如果你是直接写的引用路劲而没有使用 static 模板标签,那么你可能需要改 N 个地方。如果你使用了 static 模板标签,那么只要在 settings.py 处改一个地方就可以了,即把 STATIC_URL = ''/static/'' 改成 STATIC_URL = ''/resource/''

有时候按 F5 刷新后页面还是很乱,这可能是因为浏览器缓存了之前的结果。按 Shift + F5(有些浏览器可能是 Ctrl + F5)强制刷新浏览器页面即可。

注意这里有一个 CSS 文件的引入

<link rel="stylesheet" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">

我们没有使用模板标签,因为这里的引用的文件是一个外部文件,不是我们项目里 staticblogcss 目录下的文件,因此无需使用模板标签。

正确引入了静态文件后样式显示正常了。

正确引入静态资源后的博客首页

修改模板

目前我们看到的只是模板中预先填充的一些数据,我们得让它显示从数据库中获取的文章数据。下面来稍微改造一下模板:

在模板 index.html 中你会找到一系列 article 标签:

templates/blog/index.html

...
<article>
  ...
</article>

<article>
  ...
</article>

<article>
  ...
</article>
...

这里面包裹的内容显示的就是文章数据了。我们前面在视图函数 index 里给模板传了一个 post_list 变量,它里面包含着从数据库中取出的文章列表数据。就像 Python 一样,我们可以在模板中循环这个列表,把文章一篇篇循环出来,然后一篇篇显示文章的数据。要在模板中使用循环,需要使用到前面提到的模板标签,这次使用 {% for %} 模板标签。将 index.html 中多余的 article 标签删掉,只留下一个 article 标签,然后写上下列代码:

templates/blog/index.html

...
{% for post in post_list %}
  <article>
    ...
  </article>
{% empty %}
  <div>暂时还没有发布的文章!</div>
{% endfor %}
...

可以看到语法和 Python 的 for 循环类似,只是被 {% %} 这样一个模板标签符号包裹着。{% empty %} 的作用是当 post_list 为空,即数据库里没有文章时显示 {% empty %} 下面的内容,最后我们用 {% endfor %} 告诉 Django 循环在这里结束了。

你可能不太理解模板中的 postpost_list 是什么。post_list 是一个 QuerySet(类似于一个列表的数据结构),其中每一项都是之前定义在 blogmodels.py 中的 Post 类的实例,且每个实例分别对应着数据库中每篇文章的记录。因此我们循环遍历 post_list ,每一次遍历的结果都保存在 post 变量里。所以我们使用模板变量来显示 post 的属性值。例如这里的 {{ post.pk }}(pk 是 primary key 的缩写,即 post 对应于数据库中记录的 id 值,该属性尽管我们没有显示定义,但是 Django 会自动为我们添加)。

现在我们可以在循环体内通过 post 变量访问单篇文章的数据了。分析 article 标签里面的 HTML 内容,h1 显示的是文章的标题,

<h1>
    <a href="single.html">Adaptive Vs. Responsive Layouts And Optimal Text Readability</a>
</h1>

我们把标题替换成 posttitle 属性值。注意要把它包裹在模板变量里,因为它最终要被替换成实际的 title 值。

<h1>
    <a href="single.html">{{ post.title }}</a>
</h1>

下面这 5 个 span 标签里分别显示了分类(category)、文章发布时间、文章作者、评论数、阅读量。

<div>
  <span><a href="#">Django 博客教程</a></span>
  <span><a href="#"><timedatetime="2012-11-09T23:15:57+00:00">2017年5月11日</time></a></span>
  <span><a href="#">追梦人物</a></span>
  <span><a href="#">4 评论</a></span>
  <span><a href="#">588 阅读</a></span>
</div>

再次替换掉一些数据,由于评论数和阅读量暂时没法替换,因此先留着,我们在之后实现了这些功能后再来修改它,目前只替换分类、文章发布时间、文章作者:

<div>
  <span><a href="#">{{ post.category.name }}</a></span>
  <span><a href="#"><timedatetime="{{ post.created_time }}">{{ post.created_time }}</time></a></span>
  <span><a href="#">{{ post.author }}</a></span>
  <span><a href="#">4 评论</a></span>
  <span><a href="#">588 阅读</a></span>
</div>

这里 p 标签里显示的是摘要

<div>
  <p>免费、中文、零基础,完整的项目,基于最新版 Django 1.10 和 Python 3.5。带你从零开始一步步开发属于自己的博客网站,帮助你以最快的速度掌握 Django
    开发的技巧...</p>
  <div>
    <a href="#">继续阅读 <span>→</span></a>
  </div>
</div>

替换成 post 的摘要:

<div>
  <p>{{ post.excerpt }}</p>
  <div>
    <a href="#">继续阅读 <span>→</span></a>
  </div>
</div>

再次访问首页,它显示:暂时还没有发布的文章!好吧,做了这么多工作,但是数据库中其实还没有任何数据呀!接下来我们就实际写几篇文章保存到数据库里,看看显示的效果究竟如何。

总结

本章节的代码位于:Step6: real blog index view。

如果遇到问题,请通过下面的方式寻求帮助。

  • 在 真正的 Django 博客首页视图 - 追梦人物的博客 的评论区留言。

  • 将问题的详细描述通过邮件发送到 djangostudyteam@163.com,一般会在 24 小时内回复。

更多Django 教程,请访问 追梦人物的博客。

Django 基础之(九)drf介绍.md

Django 基础之(九)drf介绍.md

DRF

为什么要进行前后端分离

  • PC,APP,PAD多端适配
  • SPA开发模式的流行
  • 前后端职责不清
  • 前后端开发效率问题,前后端相互等待
  • 前段一直配合后端,能力受到限制
  • 后端开发语言和模板高度耦合,导致开发语言依赖严重

前后端分离的缺点

  • 前后端学习门槛增加
  • 数据依赖,导致文档的重要性增加
  • 前段工作量加大
  • SEO难度增大
  • 后端开发迁移成本增加

Restful API

restfull api目前是前后端分离的最佳实践

  • 轻量,直接通过http,不需要额外的协议,post/get/put/delete操作
  • 面向资源,一面了然,具有自解释性
  • 数据描述简单,一般是通过json或者xml做数据通信

参考博客:

  • http://www.ruanyifeng.com/blo...
  • http://www.ruanyifeng.com/blo...

今天关于Django 系列博客的分享就到这里,希望大家有所收获,若想了解更多关于Anaconda+django写出第一个web app(九)、Django 博客开发教程 3 - 创建 Django 博客的数据库模型、Django 博客开发教程 6 - 真正的 Django 博客首页视图、Django 基础之(九)drf介绍.md等相关知识,可以在本站进行查询。

本文标签:

上一篇Django 系列博客(十)(django blog)

下一篇Django 系列博客(八)(django blog)