1、Django 博客教程:前言Django 是使用 Python 编写的一个开源 Web 框架,可以用它来快速搭建一个高性能的网站。Django makes it easier to build better Web apps more quickly and with less code.Django 让你以更快的速度、更少的代码、更轻松的方式搭建更好的 Web 应用。本教程将带你使用 Django 快速开发属于自己的博客网站。教程特点免费、中文、零基础,完整的项目,基于最新版 Django 1.10 和 Python 3.5。带你从零开始一步步开发属于自己的博客网站,帮助你以最快的速度掌握 Django 开发的技巧。谁适合这个教程本教程主要面向零基础的 Django 新人。只需要一点点 Python 语言的基础,就可以顺利阅读本教程。如果你已有一定的 Django 开发经验,也能从本教程中学到更多的 Django 开发技巧。在线预览点击预览:Django 博客项目在线预览(http://demo.zmrenwu.com/)资源列表项目完整代码托管在 GitHub:Django Blog Tutorial(https://github.com/zmrenwu/django-blog-tutorial)博客前端模板托管在 GitHub:博客模板(https://github.com/zmrenwu/django-blog-tutorial-templates)2、 搭建开发环境本教程使用的开发环境本教程写作时开发环境的系统平台为 Windows 10 (64 位),Python 版本为 3.5.2 (64 位),Django 版本为 1.10.6。建议尽可能地与教程的开发环境保持一致(尤其是 Python 与 Django 版本),避免不必要的麻烦。推荐的 Python 版本为 Python 3.4 或以上,Django 版本号必须为 Django 1.10.x。注意:本教程将尽量保证兼容 Python 2,但不会在 Python 2 环境下做测试。如果你因为某种原因必须使用 Python 2,你可以在 Python 2 环境下尝试运行教程里的代码,应该能够顺利运行。安装 PythonWindows 下安装 Python 非常简单,去 Python 官方网站找到 Python 3 的下载地址,根据你的系统选择 32 位或者 64 位的安装包,下载好后双击安装即可。安装完后检测 Python 是否可以正常运行。在命令行输入 python -v ,如果输出了 Python 的版本号,说明 Python 已安装成功。C:\WINDOWS\system32>python -VPython 3.5.2如果提示命令未找到,而你又确定已经安装了 Python,多半是因为没有把 Python 添加到环境变量。可搜索如何把 Python 添加到环境变量的相关教程,将安装的Python 添加到环境变量即可。使用虚拟环境 Virtualenv强烈推荐在 Virtualenv 下进行 Django 的开发。Virtualenv 是一个 Python 工具,使用它可以创建一个独立的 Python 环境。为什么要使用 Virtualenv 呢?举个例子,假设你已经在系统中安装了 Python,并且在阅读此教程前你已经进行过一些 Django 的学习,但那时候安装的 Django 还是 1.8 版本。我们教程使用的是最新版的 Django 1.10.6 版本,你可能不愿意删除掉旧版的 Django 1.8,因为那可能导致你以前的项目无法运行。既想让原本项目在 Django 1.8 环境下运行,又想再安装 Django 1.10.6 来开启本教程的项目,怎么办呢?使用 Virtualenv 就能够完美解决这个问题。Virtualenv 帮我们从系统的 Python 环境中克隆一个全新的 Python 环境出来,这个环境独立于原来的 Python 环境。我们可以在这个新克隆的环境下安装 Django 1.10.6,并且在这个新环境下运行我们的新项目。Virtualenv 的使用非常简单,首先安装 Virtualenv,打开命令行工具,输入pip install virtualenv 命令即可安装 Virtualenv。C:\WINDOWS\system32>pip install virtualenv安装成功后就可以开始创建虚拟环境,指定一个你喜欢的目录,Virtualenv 会把这个新的虚拟环境装到你指定目录下。例如我把它装到 C:\Users\yangxg\Envs 目录下,并将虚拟环境命名为 blogproject_env(也可以取任何你喜欢的名字)。在命令栏运行如下命令:C:\WINDOWS\system32>virtualenv C:\Users\yangxg\Envs\blogproject_env虚拟环境已经创建好了,我们需要激活这个环境,运行 blogproject_env\Scripts\ 目录下的 activate 程序激活它:C:\WINDOWS\system32>C:\Users\yangxg\Envs\blogproject_env\Scripts\activate(blogproject_env) C:\WINDOWS\system32>注意 Linux 下没有 Scripts\ 这个目录,取而代之的是 bin/ 目录。且激活命令为:$ source blogproject_env/bin/activate可以看到命令提示符前面多了 (blogproject_env),说明我们已经成功激活了虚拟环境,接下来就可以开始安装 Django 了。安装 DjangoDjango 的官方文档对 如何安装 Django(https://docs.djangoproject.com/en/1.10/intro/install/#install-django) 给出了详细且明确的指导,不过我们目前用不上这些,只需使用 pip 命令就可以解决问题。(blogproject_env) C:\WINDOWS\system32>pip install django==1.10.6我们用 django==1.10.6 来安装指定的 Django 版本以保证和教程中的一致。如果直接pip install django 的话有可能安装最新的 Django 发行版本,而不是 Django 1.10.6。注意命名提示符前的 (blogproject_env) 以确保你始终处在虚拟环境中,如果不小心退出了虚拟环境,先按上面的步骤重新进入再安装 Django。测试一下安装是否成功,先在命令行输入 python 以打开 Python 自带的命令栏,然后输入 import django,如果没有报错就说明 Django 安装成功。通过运行print(django.get_version()) 打印出 Django 的版本号,确保安装了正确版本的 Django。(blogproject_env) C:\WINDOWS\system32>pythonPython 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900 64 bit (AMD64)] on win32Type “help”, “copyright”, “credits” or “license” for more information.>>> import django>>> print(django.get_version())1.10.6>>>建立 Django 工程万事已经具备了,让我们来建立 Django 项目工程。Django 工程(Project)是我们项目代码的容器,例如我们博客项目中所有的代码(包括 Django 为我们自动生成的以及我们自己写的)都包含在这个工程里。其实说通俗一点就是用一个文件夹把一系列 Python 代码文件和 Django 配置文件包裹起来,这个文件夹就可以看做一个 Django 工程。我们不必亲自动手新建这个文件夹和代码文件,Django 的内置命令已经帮我们做了这些事情。例如我把博客工程的代码放在 C:\Users\yangxg\Workspace\ ,工程名我把它叫做 blogproject 。首先在命令行进入到 C:\Users\yangxg\Workspace 这个目录(如果你还停留在 Python 的命令栏里,先多按几次 Ctrl + c 键跳出来):(blogproject_env) C:\WINDOWS\system32>cd C:\Users\yangxg\Workspace然后运行如下命令创建工程:(blogproject_env) C:\Users\yangxg\Workspace>django-admin startproject blogproject再次申明一定要在虚拟环境下运行这些命令,虚拟环境的标志就是命令提示符前有 (blogproject_env) 这样的标记。以后几乎所有和 Django 有关的命令都是在虚拟环境下运行,因此在运行前一定确保先开启了虚拟环境。进入工程所在目录 C:\Users\yangxg\Workspace\(你可能设置在其它路径),会发现多了一个 blogproject\ 的目录,其内部的文件结构如下:blogproject\manage.pyblogproject\__init__.pysettings.pyurls.pywsgi.py最顶层的 blogproject\ 目录是我们刚刚指定的工程目录。blogproject\ 目录下面有一个 manage.py 文件,manage 是管理的意思,顾名思义 manage.py 就是 Django 为我们生成的管理这个项目的 Python 脚本文件,以后用到时会再次介绍。与 manage.py 同级的还有一个 blogproject\ 的目录,这里面存放了一些 Django 的配置文件,例如 settings.py、urls.py 等等,以后用到时会详细介绍。Hello Django网站需要运行在一个 Web 服务器上,Django 已经为我们提供了一个用于本地开发的 Web 服务器。在命令行工具里进入到 manage.py 所在目录,即最外层的 blogproject\ 目录下。运行 python manage.py runserver 命令就可以在本机上开启一个 Web 服务器:(blogproject_env) C:\Users\yangxg\Workspace>cd C:\Users\yangxg\Workspace\blogproject(blogproject_env) C:\Users\yangxg\Workspace\blogproject>python manage.py runserverPerforming system checks…System check identified no issues (0 silenced).You have 13 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.Run ‘python manage.py migrate’ to apply them.December 21, 2016 – 20:23:07Django version 1.10.4, using settings ‘blogproject.settings’Starting development server at http://127.0.0.1:8000/Quit the server with CTRL-BREAK.看到这样的信息表明我们的服务器开启成功。在浏览器输入 http://127.0.0.1:8000/ ,看到如下的页面提示信息:It worked! Django 工作了!注意:如果在浏览器输入 http://127.0.0.1:8000/ 后显示无法访问该网站,请检查是不是浏览器代理的问题。比如开启了某些 VPN 代理服务等,将它们全部关闭即可。这是 manage.py 的第一个用法,运行它的 runserver 命令开启本地开发服务器,以后我们还会遇到更多的命令。命令栏工具下按 Ctrl + c 可以退出开发服务器(按一次没用的话连续多按几次)。重新开启则再次运行 python manage.py runserver 。Django 默认的语言是英语,所以显示给我们的欢迎页面是英文的。我们在 Django 的配置文件里稍作修改,让它支持中文。用任何一个文本编辑器打开 settings.py 文件,找到如下的两行代码:pythonblogproject/blogproject/settings.py## 其它配置代码…LANGUAGE_CODE = ‘en-us’TIME_ZONE = ‘UTC’## 其它配置代码…把 LANGUAGE_CODE 的值改为 zh-hans,TIME_ZONE 的值改为 Asia/Shanghai:pythonblogproject/blogproject/settings.py## 其它配置代码…# 把英文改为中文LANGUAGE_CODE = ‘zh-hans’# 把国际时区改为中国时区TIME_ZONE = ‘Asia/Shanghai’## 其它配置代码…保存更改后关闭 settings.py 文件。再次运行开发服务器,并在浏览器打开 http://127.0.0.1:8000/,可以看到 Django 已经支持中文了。总结本章节的代码位于:Step1: build development environment(https://github.com/zmrenwu/django-blog-tutorial/tree/Step1_build-development-environment)3、建立 Django 博客应用建立博客应用我们已经建立了 Django 博客的项目工程,并且成功地运行了它。不过到目前为止这一切都还只是 Django 为我们创建的项目初始内容,Django 不可能为我们初始化生成博客代码,这些功能性代码都得由我们自己编写。Django 鼓励我们把自己编写的代码组织到应用(Application)里,并且最好是一个应用只提供一种功能。例如我们要开发的 Django 博客,相关的代码都放在 blog 这个应用里。其实应用也没什么复杂的,不过是把功能相关的代码组织到一个文件夹里,这个文件夹就成了一个应用(姑且可以这样理解)。我们可以在 Django 工程目录下手动地建立一个文件夹,为它取个名字,并且告诉 Django 说这是一个应用。但是我们不必做这些无聊的工作,Django 已经为我们提供了自动创建应用的命令。现在就来创建我们的 Django 博客应用,我把它命名为 blog。激活虚拟环境,进入到 manage.py 文件所在的目录下,运行python manage.py startapp blog 命令即可建立一个 blog 应用:C:\WINDOWS\system32>C:\Users\yangxg\Envs\blogproject_env\Scripts\activate(blogproject_env) C:\WINDOWS\system32>cd C:\Users\yangxg\Workspace\blogproject(blogproject_env) C:\Users\yangxg\Workspace\blogproject>python manage.py startapp blog前面已经说过,manage.py 是我们的工程管理助手。上一章中我们使用了它的 runserver 命令开启了一个本地开发服务器,在这里我们使用 manage.py 的 startapp 命令创建了一个 blog 应用。应用的目录结构用资源管理器打开 manage.py 文件所在的目录,可以看到多了一个 blog\ 的目录,该目录下面的文件结构如下:blog\__init__.pyadmin.pyapps.pymigrations\__init__.pymodels.pytests.pyviews.py不同名称的文件用于存放特定功能的代码,这些将会在后面详细介绍。总之这个应用的文件夹结构 Django 已经为我们建立好了,但它还只是包含各种文件的一个文件夹而已,Django 目前还不知道这是一个应用。我们得告诉 Django 这是我们建立的应用,专业一点说就是在 Django 的配置文件中注册这个应用。打开 blogproject\ 目录下的 settings.py 文件,看名字就知道 settings.py 是一个设置文件(setting 意为设置),找到 INSTALLED_APPS 设置项,将 blog 应用添加进去。pythonblogproject/blogproject/settings.py## 其他配置项…INSTALLED_APPS = [‘django.contrib.admin’,’django.contrib.auth’,’django.contrib.contenttypes’,’django.contrib.sessions’,’django.contrib.messages’,’django.contrib.staticfiles’,’blog’, # 注册 blog 应用]## 其他配置项…可以看到 Django 已经为我们提供了一些内置的应用,这些应用提供了各种各样的功能。这就是 Django 强大的地方,通用的功能 Django 都帮我们写好了,我们只需编写与自身业务相关的功能代码即可。总结本章节的代码位于:Step2: create blog app(https://github.com/zmrenwu/django-blog-tutorial/tree/Step2_create-blog-app)4、创建 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 只要求我们这样写:pythonblog/models.pyfrom django.db import modelsclass Category(models.Model):name = models.CharField(max_length=100)Category 就是一个标准的 Python 类,它继承了 models.Model 类,类名为 Category 。Category 类有一个属性 name,它是 models.CharField的一个实例。这样,Django 就可以把这个类翻译成数据库的操作语言,在数据库里创建一个名为 category 的表格,这个表格的一个列名为 name。还有一个列 id,Django 则会自动创建。可以看出从 Python 代码翻译成数据库语言时其规则就是一个 Python 类对应一个数据库表格,类名即表名,类的属性对应着表格的列,属性名即列名。我们需要 3 个表格:文章(Post)、分类(Category)以及标签(Tag),下面就来分别编写它们对应的 Python 类。模型的代码通常写在相关应用的 models.py 文件里。已经在代码中做了详细的注释,说明每一句代码的含义。但如果你在移动端下阅读不便的话,也可以跳到代码后面看正文的里的讲解。注意:代码中含有中文注释,如果你直接 copy 代码到你的文本编辑器且使用了 Python 2 开发环境的话,会得到一个编码错误。因此请在文件最开始处加入编码声明:# coding: utf-8。pythonblog/models.pyfrom django.db import modelsfrom django.contrib.auth.models import Userclass 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/#relationshipscategory = 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)博客模型代码代码详解首先是 Category 和 Tag 类,它们均继承自 model.Model 类,这是 Django 规定的。 Category和 Tag 类均有一个name 属性,用来存储它们的名称。由于分类名和标签名一般都是用字符串表示,因此我们使用了CharField 来指定 name 的数据类型,同时max_length 参数则指定 name 允许的最大长度,超过该长度的字符串将不允许存入数据库。除了 CharField ,Django 还为我们提供了更多内置的数据类型,比如时间类型DateTimeField、整数类型 IntegerField 等等。在本教程中我们会教你这些类型的使用方法,但以后你开发自己的项目时,你就需要通过阅读Django 官方文档关于字段类型的介绍(https://docs.djangoproject.com/en/1.10/ref/models/fields/) 来了解有哪些数据类型可以使用以及如何使用它们。Post类也一样,必须继承自 model.Model 类。文章的数据库表稍微复杂一点,主要是列更多,我们指定了这些列:title。这是文章的标题,数据类型是 CharField,允许的最大长度 max_length = 70。body。文章正文,我们使用了 TextField。比较短的字符串存储可以使用 CharField,但对于文章的正文来说可能会是一大段文本,因此使用 TextField 来存储大段文本。created_time、modified_time。这两个列分别表示文章的创建时间和最后一次修改时间,存储时间的列用 DateTimeField 数据类型。excerpt。文章摘要,可以没有文章摘要,但默认情况下CharField 要求我们必须存入数据,否则就会报错。指定 CharField 的 blank=True参数值后就可以允许空值了。category 和 tags。这是分类与标签,分类与标签的模型我们已经定义在上面。我们把文章对应的数据库表和分类、标签对应的数据库表关联了起来,但是关联形式稍微有点不同。我们规定一篇文章只能对应一个分类,但是一个分类下可以有多篇文章,所以我们使用的是ForeignKey,即一对多的关联关系。而对于标签来说,一篇文章可以有多个标签,同一个标签下也可能有多篇文章,所以我们使用ManyToManyField,表明这是多对多的关联关系。同时我们规定文章可以没有标签,因此为标签 tags 指定了 blank=True。author。文章作者,这里 User 是从 django.contrib.auth.models 导入的。django.contrib.auth 是 Django 内置的应用,专门用于处理网站用户的注册、登录等流程。其中 User 是 Django 为我们已经写好的用户模型,和我们自己编写的 Category 等类是一样的。这里我们通过ForeignKey 把文章和User关联了起来,因为我们规定一篇文章只能有一个作者,而一个作者可能会写多篇文章,因此这是一对多的关联关系,和 Category 类似。理解多对一和多对多两种关联关系我们分别使用了两种关联数据库表的形式:ForeignKey 和 ManyToManyField。ForeignKeyForeignKey表明一种一对多的关联关系。比如这里我们的文章和分类的关系,一篇文章只能对应一个分类,而一个分类下可以有多篇文章。反应到数据库表格中,它们的实际存储情况是这样的:| 文章 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 官方参考资料。ManyToManyFieldManyToManyField表明一种多对多的关联关系,比如这里的文章和标签,一篇文章可以有多个标签,而一个标签下也可以有多篇文章。反应到数据库表格中,它们的实际存储情况是这样的:| 文章 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 简介(https://docs.djangoproject.com/en/1.10/topics/db/models/#relationships)Django ForeignKey 详细示例(https://docs.djangoproject.com/en/1.10/topics/db/examples/many_to_one/)Django ManyToManyField 简介(https://docs.djangoproject.com/en/1.10/topics/db/models/#many-to-many-relationships)Django ManyToManyField 详细示例(https://docs.djangoproject.com/en/1.10/topics/db/examples/many_to_many/)总结本章节的代码位于:Step3: blog models(https://github.com/zmrenwu/django-blog-tutorial/tree/Step3_blog-models)End.运行人员:中国统计网小编(微信号:itongjilove)微博ID:中国统计网中国统计网,是国内最早的大数据学习网站,公众号:中国统计网http://www.itongji.cn