Django 是一个用 python 写的 web 服务器。它的优势在于开发的简便性和低门槛, 高度强调可复用性和可插拔性。它内置了大量组建, 还自带与数据库联动的后台管理系统.

Django 初探

Django 采用 MTV 框架模式。即 Model, Template, View. 和现在流行的 MVC 在名称上不太相同.

MVC MTV
数据模型 Model Model
用户界面 View Template
业务逻辑 controller View

Django 提供了用于管理 Django 项目的命令 django_admin, 由他生成的项目骨架为

```

项目名
├── 项目名 // 项目全局文件目录
│ ├── __init__.py
│ ├── settings.py // 全局配置
│ ├── urls.py // 全局路由
│ └── wsgi.py // WSGI服务接口(暂时不用纠结这个是神马)
└── manage.py // 项目管理脚本

## App

Django应子应用组织起来, 那些子应用被称为App. 和项目名相同的那个App是主App

所有的Django App都在`settings.py`的*INSTALLED_APPS*中定义.

一个App的文件结构如下所示

```txt
应用名 // news 应用目录
├── __init__.py // 初始化模块
├── admin.py // 后台管理配置
├── apps.py // 应用配置
├── migrations // 数据库迁移文件目录
│ └── __init__.py // 数据库迁移初始化模块
├── models.py // 数据模型
├── templates // 模板目录
│ └── 命名空间 // 该App的模板的命名空间目录
│ └── 模板文件.html// 该App的模板的命名空间目录
├── tests.py // 单元测试
├── urls.py // 单元测试
└── views.py // 视图

路由系统

Django 的路由系统是由全局路由和子应用路由组成,根据用户输入的 URL, 全局路由表先匹配第一级路径,再由子路由匹配第二级路径.

子路由表就是 App 里的 urls.py 文件. 它里面包含一个 urlpatterns 列表来存放路由映射表, 通常用 django.urls.path 函数来生成元素. 这个函数接受以下参数:

  1. route: 实际访问的路由,'' 意为 /
  2. view: 该路由要访问的视图
  3. name: 可选,这条路由的名字.

全局路由就是主 App 里的 url.py 文件. 里面也是一个 urlpattern.

另外, django.urls 里面还提供了一个 include 函数, 接受一个表示模块名的字符串,返回对应的模块对象.

django.urls.reverse 可以根据视图名和相关参数反查 URL.

视图

Django 支持基于函数和基于类的视图。视图为模板文件提供需要的参数值.

视图文件 views.py 定义了函数 index. 它接受一个 request 参数, 返回由 render 函数返回的对象. render 主要接受三个参数: 1. request: 请求对象. 2. template_name: 模板名称. 3. context: 为模板提供的值。字典类型, 每一个键对应模变里的同名变量.

模板语法和 vue 类似

每个 App 都有自己的模板,在 templates 下, 由于 Django 的模板查找机制会将所有 App 里的模板收集到一起, 因此推荐在 templates 下再建立命名空间文件夹存放模范文件, 防止模板名冲突.

模型

Django 使用模型来对应底层的数据库模型。它有着相当多的优点: + 高度解耦的设计,可以轻松切换关系型数据库 + ORM 模块提供了良好的 SQL 封装 + 优秀的数据库迁移机制和数据模式修改机制

模型写在 App 的 models.py 文件. 每个表都是一个继承 django.db.models.Model 的类,称为数据类. 每个类域代表该表的一个字段, 用 django.db.models. 里对应类型的对象初始化.

数据类用__str__的返回值描述对象的状态.

模型 API

既然数据库模型的创建被封装成了 Python, 没理由其它操作没有 Python 封装.

每个数据类都继承了 django.db.models.Model. 它里面有一个 objects 类对象. 该对象封装了大量的数据库增删改查操作。比如 filter(**kwargs). 它除了可以做简单的字段筛选, 还可以在字段后面添加__操作表示对该字段经过某个操作处理后的值筛选.

在视图中, 模板通过 django.template.loader.get_template(模板路径) 导入, 然后调用模板对象的 render(请求, 上下文) 方法来得到解析后的 HTML 字符串.

通过迁移系统更新数据库

模型写在 python 文件里,但是服务器运行的时候是从数据库里读取数据, 把 models.py 里的内容反映到数据库的过程叫做迁移.

所有 App 的 models.py 文件可以通过 makemigrations 生成迁移文件, 在每个 App 的 migrations 文件夹里.

可以给 sqlmigrate 命令提供 App 名字和迁移文件编号来查看对应的迁移文件会被翻译成什么样的 SQL 语句.

迁移文件通过 migrate 应用到数据库中. 这个命令的意思就是把数据库状态同步为 model 和迁移. 如果在 admin.py 里通过 django.contrib.admin.site.register(数据模型类) 注册后, 登录到后台就可以看到啦。可以利用这个数据模型批量添加数据, 把数据模型类注册到视图里就可以在主页上显示啦.

之所以要经过迁移文件倒一道手而不是直接迁移, 是因为迁移文件可以部署到生产环境中或者供其他开发人员使用.

注意事项

  • 在主 App 的 settings.py 中把 time_zone 改为 Asia/Shanghai
  • 模板中要对使用 POST 提交的 form 要加上 {% csrf_token %} 行来进行安全验证.
  • 在处理完 POST 数据后,记得返回 HttpResponseRedirect.

测试

Django 提供两种测试手段, 一种是基于 unittset 的单元测试方式. 另一种是测试视图的 Client 方式.

单元测试

类似 unittest. 在 test.py 中, 一个继承了 django.test.TestCase 的类测试一个模型. 测试函数需要以 test 开头, 并通过 self 调用对应的断言函数进行测试.

可以看到,这种测试方式更适合测试模型和模板, 但是对于视图就不是特别方便啦。因此我们有 Client 测试

Client 测试

这种测试方式首先需要你调用 django.test.utils.setup_test_environment() 建立测试环境.

然后,可以实例化一个 django.test.Client 对象。它顾名思义, 它扮演类似 Http 的客户端的角色. 可以调用它的 get() 等方法得到一个 django.http.response.HttpResponse 对想. 它保存着 django 服务器的回应内容.

引用