Django 框架快速上手
Web 应用早期开发,需要手动编写和更新每个 HTML 页面,在大型网站中很难维护和扩展,动态生成内容的技术(如 CGI 和 后来更现代的 PHP、ASP、JSP)显著提升了 Web 应用的效率与可维护。性。
通常,所说的 Web 应用指通过浏览器来访问网络资源的应用程序。Web 应用使用起来方便,免除了安装和更新应用程序带来的麻烦。开发者也不用关心用户使用什么操作系统。
Web 应用机制和术语
Web 应用的工作流程图,大致如下:
Web 应用逻辑调用时序图:
相关术语:
术语 | 解释 |
---|---|
URL/URI | 统一资源定位符/统一资源标识符,网络资源的唯一标识 |
域名 | 与Web服务器地址对应的一个易于记忆的字符串名字 |
DNS | 域名解析服务,可以将域名转换成对应的IP地址 |
IP地址 | 网络上的主机的身份标识,通过IP地址可以区分不同的主机 |
HTTP | 超文本传输协议,构建在TCP之上的应用级协议,万维网数据通信的基础 |
反向代理 | 将客户端请求转发给后端的 Web 服务器或应用服务器,后端逻辑处理做出响应,反向代理服务器再将后端的响应转发回客户端 |
Web 服务器 | 处理客户端的请求并返回相应内容。通常将静态文件(HMTL、CSS、JavaScript、图片等)直接返回给客户端,或将请求转发给应用服务器处理动态内容。Nginx 是高性能的 Web 服务器,也可以用作反向代理,负载均衡 和 HTTP缓存 |
Web 应用服务器 | 应用服务器通常托管应用程序,处理客户端的请求处理动态内容(如数据库查询和应用逻辑) |
数据库服务器 | 存储和管理应用所需的数据,处理对数据的创建、读取、更新和删除(CRUD)操作 |
HTTP 协议
HTTP(超文本传输协议)是构建于 TCP(传输控制协议)之上应用层协议,它利用了 TCP 提供的可靠的传输服务实现了 Web 应用中的数据交换。
按照维基百科上的介绍,设计 HTTP 最初的目的是为了提供一种发布和接收 HTML页面的方法,也就是说这个协议是浏览器和Web服务器之间传输的数据的载体。
关于这个协议的详细信息以及目前的发展状况,参考阅读《HTTP 协议入门》、《互联网协议入门》系列以及《图解HTTPS协议》。
开源协议分析工具 Ethereal(抓包工具 WireShark 的前身),它可以抓取和分析网络适配器上通过的网络数据包,包括所有协议层的数据,从物理链路层到应用层。例如,通过这个工具,可以观察到访问百度首页时所产生的详细 HTTP 请求和响应报文。
HTTP 请求
在 HTTP 请求中,数据通常分为以下几个部分:请求行、请求头、空行和消息体。
请求行:
请求行是每个 HTTP 请求的第一行,包含以下信息:
- 请求方法(如 GET、POST、PUT、DELETE):指定客户端想要对资源执行的操作。
- 请求 URL:指定资源的地址,通常包括协议(如
http
或https
)、主机名和路径等。 - HTTP 版本:指定客户端支持的 HTTP 版本,例如
HTTP/1.1
或HTTP/2
。
示例:
GET /index.html HTTP/1.1
这里,GET
是请求方法,/index.html
是请求的资源,HTTP/1.1
是协议版本。
请求头:
请求头包含了客户端与服务器之间的各种信息,例如客户端信息、缓存控制、授权信息等。常见的请求头包括:
Host
:指定服务器的域名和端口号。User-Agent
:指定发送请求的浏览器或客户端软件的详细信息。Accept
:指定客户端能接受的内容类型(如text/html
、application/json
)。Content-type
:指定请求体的内容类型,通常在POST
或PUT
请求中使用。Authorization
: 如果请求需要身份验证,包含认证信息。
空行:
请求头和请求体之间有一个空行,用于分隔请求头和请求体。空行是必须的,表示头部字段的结束。
消息体:
请求体仅在某些请求方法中使用(如 POST
、PUT
或 PATCH
)。它包含了要发送的数据,通常用于提交表单、上传文件或发送 JSON 数据等。
POST 请求示例:
POST /submit-form HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Content-Length: 25
name=John&age=30&city=NewYork
说明:该请求体包含了表单数据: name=John&age=30&city=NewYork
。
HTTP 响应
HTTP 响应报文通常包含以下几个部分:响应行、响应头、空行、响应体。
响应行:
响应行是 HTTP 响应的第一行,包含了三部分信息:
- HTTP 版本(例如
HTTP/1.1
或HTTP/2
)。 - 状态码(如
200
、404
)。 - 状态描述(例如
OK
,Not Found
)。
响应头:
响应头包含了多种元信息,描述服务器和返回的数据。常见的响应头字段包括:
Content-Type
:响应体的内容类型(如text/html
、application/json
)。Content-Length
:响应体的大小(以字节为单位)。Date
:响应生成的日期。Server
:响应的服务器信息。Cache-Control
:缓存控制,指示缓存的处理方式。
空行:
响应头与响应体之间必须有一个空行(即仅包含 CRLF,\r\n
)。这个空行用于分隔头部和消息体。
响应体:
响应体包含了实际的数据内容,也就是客户端请求的资源(如 HTML 文件、JSON 数据、图片等)。根据请求的资源类型,响应体的内容和格式可能有所不同。
HTTP 响应示例:
HTTP/1.1 200 OK
Date: Sun, 27 Jun 2024 12:28:53 GMT
Server: Apache/2.4.41 (Ubuntu)
Content-Type: application/json
Content-Length: 48
{
"status": "success",
"message": "Data received"
}
说明:响应体包含服务器返回的实际数据,此例中,响应体是一个 JSON 格式的数据。
了解更多 HTTP 响应状态码
Web 框架
Web 框架是用于开发 Web 服务器端应用的基础设施,是一系列封装好的模块和工具。
没有 Web 框架,也可以通过 socket 或 CGI 来开发 Web 服务器端应用,但是这样做的成本和代价相对较大。
通过 Web 框架,可以让开发工作化繁为简,降低更新扩展应用程序的工作量。Python 有上百个 Web 框架,这些框架包括 Django、Flask、Tornado、Sanic、Pyramid、Bottle、Web2py、web.py 等。
其中,Django 是最具代表性的轻量级框架,开发者可以基于 Django 快速地开发可靠的 Web 应用程序。
Django 概述
Django 框架对常用的设计和开发模式进行了封装,并对 MVC 架构(在 Django 中称之为 MTV 架构)提供了支持。
MVC 架构将系统中的组件分为模型(Model)、视图(View)和控制器(Controller)三部分。并借此实现模型数据和视图显示的解耦合。由于模型和视图进行了分离,所以需要一个中间角色将解耦合的模型和视图联系起来,这个角色就是控制器。
稍具规模的软件系统都会使用 MVC 架构(或以其演进的架构),Django 项目中我们称之为 MTV。MTV 中的 M
与 MVC 中 M
没有区别,代表数据的模型,T
代表网页模板即显示数据的视图,V
代表视图函数。在 Django 框架中,视图函数和 Django 框架本身一起扮演 MVC 中的 C
的角色。
创建 Django 项目
注意:Django 框架不同版本所需要的 Python 解释器环境不同,可以在 Django 官方文档的 FAQ 中查看。
对于每个版本的 Python,官方仅支持最新的三级版本(A.B.C)。你可以在 Python下载页面 找到每个系列的微版本。
检查 Python 解释器版本
终端命令行下执行查询:
python --version
# 或者
python3 --version
交互式环境查看 Python 版本号:
import sys
sys.version
'3.9.13 (tags/v3.9.13:6de2ca5, May 17 2022, 16:36:42) [MSC v.1929 64 bit (AMD64)]'
sys.version_info
sys.version_info(major=3, minor=9, micro=13, releaselevel='final', serial=0)
更新包管理工具并安装 Django
pip install Django==4.0.7
说明:使用 Django==
可以指定安装的版本。
检查 Django 版本并创建项目
创建项目名称如:helloDjango
。
django-admin --version
django-admin startproject hellodjango
示例:
(venv) PS D:\PycharmProjects> django-admin --version
4.0.7
(venv) PS D:\PycharmProjects> django-admin startproject helloDjango
添加虚拟环境
使用 Pycharm 打开创建的 Django 项目,并为其添加虚拟环境。
如上图所示,PyCharm 的项目浏览器中,最顶层的文件夹hellodjango
是 Python 项目文件夹。该文件夹下有一个同名的文件夹,它是Django 项目文件夹,其中包含的主要文件如下所示:
hellodjango/__init__.py
:空文件,告诉 Python 解释器这个目录应该被视为一个 Python 的包。hellodjango/asgi.py
:一个 ASGI 兼容的应用服务器网关接口文件。用于将 Django 项目部署到 ASGI 兼容的应用服务器上,如 Daphne、Uvicorn 等。hellodjango/settings.py
:Django 项目的配置文件。包含了项目的设置,如数据库配置、静态文件路径、模板路径、应用程序配置等。hellodjango/urls.py
:Django 项目的 URL 映射声明,将 URL 映射到视图函数,就像是网站的“目录”。hellodjango/wsgi.py
:一个 WSGI 兼容的 Web 服务器网关接口文件。用于将 Django 项目运行在 WSGI 兼容 Web 服务器上,如 Apache、Nginx 等。manage.py
: 管理 Django 项目的脚本程序。用于执行各种 Django 管理命令,如运行开发服务器、创建应用程序、执行数据库迁移等。
说明:WSGI 全称是 Web 服务器网关接口,是为 Python 语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口”。
在该项目目录添加解释器环境,创建虚拟环境的界面如下图所示:
安装项目依赖项
方法一:在 Pycharm 的偏好设置中,找到该项目的解释器环境和已经安装的三方库页面:可以通过点击添加(+
)按钮来安装新的依赖项,安装 Django 依赖项时,需要指定版本号,否则将默认安装更新最新的版本。
方法二: 打开 Pycharm 的终端,在终端中通过 pip
命令安装 Django 项目的依赖项。
由于已经在基于
Python 3
解释器环境为项目创建了虚拟环境,所以,虚拟环境中的python
命令对应的是Python 3
的解释器,而pip
命令对应的是Python 3
的包管理工具。
pip install django==4.0.7
启动 Django 项目服务器
在开发环境中,Django 自带了一个轻量级的开发服务器,便于调试和开发应用程序。因此,可以启动 Django 框架自带的服务器运行 Django 项目程序。
方法一:在 Run
菜单选择 Edit Configuration
,配置 Python
程序运行项目(适用于专业版和社区版 PyCharm)
方法二:在 Run
菜单选择 Edit Configuration
,配置 Django server
运行项目(适用于专业版 PyCharm)。
方法三:在 PyCharm 的终端(Terminal
)中通过命令运行项目(适用于专业版和社区版 PyCharm)。
(venv) PS D:\PycharmProjects\helloDjango> python manage.py runserver
查看运行效果
在浏览器中输入http://127.0.0.1:8000
访问我们的服务器,效果如下图所示。
说明:
- Django 自带的服务器只能用于开发和测试环境,它是纯 Python 编写的轻量级 Web 服务器,不适合在生产环境中使用。
- 如果修改了代码,不需要重新启动 Django 自带的服务器。但是,在添加新的项目文件后,需要手动重启服务器以便加载生效。
- 在终端中,可以通过
python manage.py help
命令查看 Django 管理脚本程序可用的命令参数。 - 使用
python manage.py runserver
启动服务器,默认情况下运行在本机的8000
端口,可以在命令后指定 IP 地址和端口号。 - 在终端中运行的服务器,可以使用
Ctrl+C
停止。通过 PyCharm 的“运行配置”运行的服务器直接点击窗口上的关闭按钮终止运行。 - 不能在同一个 IP 地址和端口上同时启动多个服务器,因为每个端口只能由一个进程绑定。
修改配置文件 setting.py
Django 是一个支持国际化和本地化的框架,Django 项目的默认首页是显示成支持国际化的,因此,可以通过修改项目的配置文件 setting.py
将默认语言修改为中文,时区设置为东八区。
setting.py
文件默认配置:
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
修改内容如下:
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Chongqing'
直接刷新刚才的页面,可以看到修改显示语言和时区的效果。
创建 Web 应用
如果要开发自己的 Web 应用,需要先在 Django 项目中创建“应用”,一个 Django 项目可以包含一个或多个应用。
创建应用
在 Pycharm 的终端中执行如下命令,创建名为 first
的应用:
(venv) PS D:\PycharmProjects\helloDjango> python manage.py startapp first
执行上面的命令会在当前路径下创建 first
目录,其目录结构如下所示:
migrations
:存放与模型有关的数据库迁移信息。__init__.py
:一个空文件,告诉 Python 解释器这个目录应该被视为一个 Python 的包。
__init__.py
:一个空文件,告诉 Python 解释器这个目录应该被视为一个 Python 的包。admin.py
:用于注册模型,在 Django 框架自带的管理后台中管理模型。apps.py
:当前应用程序的表单配置文件。包含了应用程序的表单类定义,用于生成 HTML 表单并验证用户输入。models.py
:存放应用的数据模型(MTV 中的M
)。用于与数据库交互。tests.py
:包含测试应用各项功能的测试类和测试函数。views.py
:处理用户 HTTP 请求并返回 HTTP 响应的视图函数或视图类(MTV 中的V
)。
定义视图
修改应用目录下的视图文件 views.py
:
from django.http import HttpResponse
def show_index(request):
return HttpResponse('<h1>Hello, Django!</h1>')
配置 URL 请求路由
修改 urls.py
文件,将用户在浏览器中请求的 URL 路径与对应视图函数关联。以便 Django 知道如何处理并返回正确的响应。
from django.contrib import admin
from django.urls import path
from first.views import show_index
urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', show_index),
]
运行项目
重新运行项目,并在浏览器中访问 http://127.0.0.1:8000/hello/
。页面效果如下:
我们通过上面代码在浏览器生成了内容,但目前还只是静态内容。
渲染动态网页
如果想要在网页上渲染动态内容,可以修改 views.py
文件并添加如下内容:
from django.http import HttpResponse
from random import sample
def show_index(request):
fruits = [
'Apple', 'Orange', 'Pitaya', 'Durian', 'Waxberry', 'Blueberry',
'Grape', 'Peach', 'Pear', 'Banana', 'Watermelon', 'Mango'
]
select_fruits = sample(fruits, 3)
content = '<h3>今天推荐的水果是:</h3>'
content += '<hr>'
content += '<ul>'
for fruit in select_fruits:
content += f'<li>{fruit}</li>'
content += '</ul>'
return HttpResponse(content)
刷新页面检查
刷新页面查看程序的运行结果,预期每刷新一次网页,可以看到不一样的内容。
使用模板页
因为在实际项目中的前端页面往往非常复杂,如上述手动拼接 HTML 代码显然不可取。为此,Django 提供了模板页(MTV 模式中的 T
)。
模版页中使用占位符和指令来动态渲染数据,简化了动态内容生成的问题。通过使用模板页,可以更高效地构建复杂的前端页面,使开发流程更直观。
在 Django 中,通过 render
函数渲染模板,模板引擎(如 Django 的模板系统)将动态数据与静态模板结合,生成完整的 HTML 文件并返回给客户端。这里的渲染是后端渲染,即在服务器段完成页面的渲染再输出到浏览器中。
后端渲染的做法在 Web 应用的访问量较大时,会使服务器承受较大的负担,所以越来越多的 Web 应用会选择前端渲染的方式,即服务器只提供页面所需要的数据(通常为 JSON 格式数据),在浏览器通过 JavaScript 代码获取这些数据并渲染页面上。
关于前端渲染的内容,后续学习[[前后端分离开发入门]]
使用模板页的操作步骤:
创建模板页文件夹
在项目目录下创建名为 templates
文件夹:
说明:将定义的页面放置在
templates
目录下,并在视图中渲染这些模板,以便用户可以访问不同的页面。
添加模板页 index.html
实际项目开发中,前端开发者提供静态页面作为模板,后端开发者会将这些页面修改为模板页,并在页面中加入占位符。通过 Python 程序,后端渲染动态内容,将相应的数据插入这些模板中,生成最终的 HTML 页面,然后返回给客户端。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
<style>
#fruits {
font-size 1.25em;
}
</style>
</head>
<body>
<h1>今天推荐的水果是:</h1>
<hr>
<ul id="fruits">
{% for fruit in fruits %}
<li>{{ fruit }}</li>
{% endfor %}
</ul>
</body>
</html>
在上面的模板页中使用了 {{ fruit }}
的模板占位符语法,也使用了 {% for %}
的模板指令,这些都是 Django 模板语言(DTL)的一部分。
关于模板指令和语法,可以了解参考官方文档。
定义视图函数
修改 views.py
文件,调用 render
函数渲染模板页。
from random import sample
from django.shortcuts import render
def show_index(request):
fruits = [
'Apple', 'Orange', 'Pitaya', 'Durian', 'Waxberry', 'Blueberry',
'Grape', 'Peach', 'Pear', 'Banana', 'Watermelon', 'Mango'
]
selected_fruits = sample(fruits, 3)
return render(request, 'index.html', {'fruits': selected_fruits})
render
函数的第一个参是请求对象 request
,第二个参数是我们要渲染的模板页的名字,第三个参数是要渲染到页面上的数据,通过一个字典将数据交给模板页,字典中的键就是模板页中使用的模板指令或占位符中的变量名。
目前,视图函数中的 render
还无法找到模板文件 index.html
,需要修改 settings.py
文件,配置模板文件所在的路径。
配置模板文件路径
修改 settings.py
,找到 TEMPLATES
配置,修改其中 DIRS
字段的配置。
import os
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'), ],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
说明:
[os.path.join(BASE_DIR, 'templates'), ]
:在列表的最后加上一个逗号,
,即使只有一个元素,也能确保这个元素被识别为列表中的单一元素。
运行项目
重新运行项目验证结果。