书籍名称:[Python3 自动化软件发布系统-Django2 实战]
Django 模块实现 Web 服务
- 将以下文件保存为
testdjango.py
。
1 | import sys |
代码解释:
- 第6~9 行定义了 Django 的 settings 里面的配置参数
- 第 11~12 行定义了 index 函数,此函数返回一个 HTTPResponse 对象
- 第 14 行定义了一个 URL,注册了一个默认路径,此路径的处理函数为 index.
- 在当前目录下运行如下命令:
1
python testdjango.py runserver
Django 新建项目应用及运行机制
新建 Django 项目应用
新建项目 django_demo_project
1
django-admin startproject django_demo_project
进入此目录,运行如下命令,新建一个 App 应用
1
django-admin startapp bbs
通过这两条命令,一个基本的 Django 项目就建立好了。
Django 目录及文件分析
在 Django 的哲学中,有两个重要的概念:Project
和 App
.
- Project: 是配置和应用程序的集合。一个项目可以由多个应用程序或一个应用程序组成。如果没有一个 Project,就无法运行 Django 应用程序。
- App: 是一个可以完成某件事情的 Web 应用程序。一个应用程序通常由一组
models
(数据库表),views
(视图),templates
(模板),tests
(测试) 组成。
到目前为止, django_demo_project 项目下的目录树如下所示:
1 | % tree django_demo_project |
下面为文件夹内的每个文件的作用讲解一下:
manage.py
[项目根目录]: 使用 django-admin 命令行工具的快捷方式。它用于运行与我们项目相关的命令。我们将使用它来运行开发服务器,运行测试,创建迁移等;django_demo_project/
: 每个 Django 项目都会有和项目名同名的目录,这里面放置了影响项目的全局性的文件;__init__.py
[django_demo_project 目录]: 这个空文件告诉 Python,这个文件夹是一个 Python 包;settings.py
[django_demo_project 目录]: 这个文件包含了所有的项目配置;urls.py
[django_demo_project 目录]: 这个文件负责映射我们项目中的路由和路径;wsgi.py
[django_demo_project 目录]: 该文件是用于部署的简单网关接口;bbs/
: 在 Django 项目里,每新建一个应用,就会生成一个同名的应用目录;migrations/
[bbs 目录]: 在这个文件夹里,Django 会存储一些文件以跟踪在 models.py 文件中创建的变更,用来保持数据库和 models.py 的同步;admin.py
[bbs 目录]: 这个文件为一个 Django 内置的应用程序Django Admin
的配置文件。如果在这里注册了 models.py 中的数据表,那么在 Admin 管理后台,就可以编辑数据表中的记录了;apps.py
[bbs 目录]: 这里是应用程序本身的配置文件。我们不在这里做过多扩展,只是使用了里面的 config 配置名称;models.py
[bbs 目录]: 这里定义 web 应用程序数据实例的地方。models 会由 Django 自动转换为数据库表;tests.py
[bbs 目录]: 这个文件用来写当前应用程序的单元测试。更专业的单元测试,会包括很多测试用例。这个 tests.py 文件,就会扩展为一个 tests 目录;views.py
[bbs 目录]: 这是处理 Web 应用程序请求(request)/响应(response)周期的文件;
Django 框架的工作机制
Django 对 HTTP 的请求回应过程如下:
- 用户通过浏览器请求一个页面;
- 请求到达 Request Middlewares,中间件对 Request 做一些预处理或者直接响应请求;
- URLConf 通过 urls.py 文件和请求的 URL 找到相应的 View;
- View Middlewares 被访问,它同样可以对 Request 做一些处理或者直接返回 Response;
- 调用 View 中的函数;
- View 中的方法可以选择性的通过 Models 访问底层的数据;
- 所有的 Model-to-DB 的交互都是通过 Manager 完成的;
- 如果需要,Views 可以使用一个特殊的 Context;
- Context 被传给 Template 用来生成页面;
- Template 使用 Filters 和 Tags 去渲染输出;
- 输出被返回到 View;
- HTTP Response 被发送到 Response Middlewares;
- 任何 Response Middlewares 都可以丰富 Response 或者返回一个完全不同的 Response;
- Response 返回到浏览器,呈现给用户。
Django 视图
在学习 Django 的工作机制时,发现 Django 最主要的几个部分分别是:Middleware
(中间件,包括 Request,View,Exception,Response),URLConf
(URL 映射关系),Template
(模板系统)。
基于函数的视图
视图是接收 HTTPRequest 对象并返回一个 HTTPResponse 对象的 Python 函数。接收 Request 作为参数并返回 Response 作为结果。
项目仍以上一节的代码为基础。这一次实践中,我们暂时不会用到模板,模型,而只是使用路由和视图来实现一个简单的 web 访问服务。操作步骤如下:
- 在 settings.py 里的 INSTALLED_APPS 加入新建的 App:
1
2
3
4
5
6
7
8
9
10# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'bbs.apps.BbsConfig',
]
代码解释:
bbs 应用目录中包含了 apps.py 文件,用于保存该应用的相关信息。将此类添加到工程 settings.py 中的 INSTALLED_APPS 列表中,表明注册安装具备此配置属性的应用;
- 在 bbs 目录下的 views.py 中生成一个 index 函数:
1
2
3
4
5
6from django.http.response import HttpResponse
# Create your views here.
def index(request):
return HttpResponse("Hello, Django!")
代码解释:
当一个页面被请求时,Django 创建一个包含请求元数据的 HTTPRequest 对象。然后 Django 调入合适的视图,把 HTTPRequest 作为该视图函数的第一个参数传入。每个视图函数都使用 HTTPRequest 对象作为第一个参数,通常称之为 Request,并返回一个 HTTPResponse 对象。实现了这样一个 输入/输出 的函数,我们就称之为一个 Django 函数视图。
- 在 django_demo_project 目录下的 urls.py 里加入此 View 的路由:
1
2
3
4
5
6
7
8
9from django.contrib import admin
from django.urls import path
from bbs import views as bbs_view
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', bbs_view.index, name='index')
]
代码解释:
- 首先引入 bbs 应用模块里的 views.py 文件,为避免引入其他的 views.py 文件导致冲突,为此文件取一个 bbs_view 的别名;
- 将 bbs 目录下的 views.py 文件中的 index 函数,注册为一个 Django 的 URL 实例。
- 此时,在 django_demo_project 目录下,运行以下命令启动 Django 服务,打开浏览器访问 http://127.0.0.1:8000/index/,就会出现视图函数中返回的的响应内容了:
1
python manager.py runserver
视图在 Django 中的实现,分为 FBV
(Function Base Views),就是在视图中使用函数
处理请求,以及 CBV
(Class Base Views),就是在视图中使用类
处理请求。
Django 中的 HttpRequest 对象
基于 Django 的 Web 服务器接收到 HTTP 协议的请求后,会根据报文创建 HttpRequest 对象,视图函数的第一个参数时 HttpRequest对象。
在 django.http.request 模块中定义了 HttpRequest 对象的 API 属性。
在此,我们列出了 HttpRequest 对象的主要属性和方法。
属性
下面的属性除非特别说明,属性都是只读的:
- path: 一个字符串,表示请求的页面的完整路径,不包含域名;
- method: 一个字符串,表示请求使用的 HTTP 方法,常用值包括
GET
,POST
; - encoding: 一个字符串,表示提交的数据的编码方式,如果为 None,则表示使用浏览器的默认设置,一般为
utf-8
,(这个属性是可写的); - get: 一个类似字典的对象,包含 get 请求方式的所有参数;
- post: 一个类似字典的对象,包含 post 请求方式的所有参数;
- files: 一个类似字典的对象,包含所有的上传文件;
- cookies: 一个标准的 Python 字典,包含所有的 cookie,键和值都为字符串;
- session: 一个即可读又可写的类似字典的对象,表示当前的会话,只有当 Django 启用会话的支持时才可用;
方法
- is_ajax(): 如果请求是通过 XMLHttpRequest 发起的,则返回 True。
Django HttpRequest 对象中的 QueryDict 对象
在 HttpRequest 对象中,GET 和 POST 属性得到的都是 django.http.QueryDict 所创建的实例。这是一个 Django 自定义的类似字典的类,用来处理同一个键带多个值的情况。
在 Python 原始字典中,当一个键出现多个值的时候会发生冲突,只保留最后一个值。而在 HTML 表单中,通常会发生一个键有多个值的情况,例如 <select multiple>
(多选框) 就是一个很常见的情况。
request.POST 和 request.GET 的 QueryDict 在一个正常的请求/响应过程中是不可变的。若要获得可变版本,需要使用 copy() 方法。其主要属性和方法如下:
GET 属性
- QueryDict 类型的对象;
- 包含 get 请求方式的所有参数;
- 与 URL 请求地址中的参数对应,位于 “?” 后面;
- 参数的格式是键值对,如 key1=value1;
- 多个参数之间,使用
“&”
连接,如 key1=value1&key2=value2; - 键是开发人员定下的,值是可变的。
POST 属性
- QueryDict 类型的对象;
- 包含 post 请求方式的所有参数;
- 与 form 表单中的控件对应;
- 控件要有 name 属性,则name 属性的值为键,value 属性的值为值,构成键值对提交;
- 对于 checkbox 控件,name 属性一样为一组,当控件被选中后会被提交,存在一键多值的情况;
- 键是开发人员定下来的,值是可变的。
Django 的 HttpResponse 对象
在 Django 中,HttpRequest 对象由 Django 自动创建,HttpResponse 对象由程序员创建,每个视图都会返回一个 HttpResponse 对象。
在 django.http.response 模块中定义了 HttpResponse 对象的 API,其主要包含属性,方法,继承子类,简写函数,如下:
属性
- content: 字符串类型,表示返回的内容;
- charset: 字符串类型,表示 Response 采用的编码字符集;
- status_code: 响应的 HTTP 响应状态码;
- content-type: 指定输出的 MIME 类型;
方法
- init: 使用页内容实例化 HttpResponse 对象;
- write(content): 以文件的方式写;
- flush(): 以文件的方式输出缓存区;
- set_cookie(key, value=’’, max_age=None, expires=None): 设置 Cookie;
- delete_cookie(key): 删除指定 key 的 Cookie,如果 key 不存在,则什么也不发生。
子类 HTTPResponseRedirect
- 重定向,服务器端跳转;
- 构造函数的第一个参数,用来指定重定向的地址;
子类 JsonResponse
- 返回 json 数据,一般用于异步请求;
- 帮助用户创建 JSON 编码的响应;
- 参数 data 是字典对象;
- JsonResponse 的默认 Content-Type 为 application/json;
简写函数 render(request, template_name[, context])
- 结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象;
- request: 该 request 用于生成 Response;
- template_name: 要使用的模板的完整名称;
- context: 添加到模板上下文的一个字典,视图将在渲染模板之前调用它。
重定向 redirect(to)
- 为传递进来的参数返回 HttpResponseRedirect;
- 推荐使用反向解析。
get_object_or_404(klass, args, *kwargs)
- 通过模型管理器或查询集调用 get() 方法,如果没找到对象,则不引发模型的 DoesNotExist 异常,而是引发 HTTP404 异常。
get_list_or_404(klass, args, *kwargs)
- 和 get_object_or_404 类似,但可以在过滤多个对象时使用。