文章

Django 框架快速上手

Web 应用早期开发,需要手动编写和更新每个 HTML 页面,在大型网站中很难维护和扩展,动态生成内容的技术(如 CGI 和 后来更现代的 PHP、ASP、JSP)显著提升了 Web 应用的效率与可维护。性。

通常,所说的 Web 应用指通过浏览器来访问网络资源的应用程序。Web 应用使用起来方便,免除了安装和更新应用程序带来的麻烦。开发者也不用关心用户使用什么操作系统。

Web 应用机制和术语

Web 应用的工作流程图,大致如下:

Pasted image 20241110214441.png

Web 应用逻辑调用时序图:

Pasted image 20241110204423.png

相关术语:

术语 解释
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:指定资源的地址,通常包括协议(如 httphttps)、主机名和路径等。
  • HTTP 版本:指定客户端支持的 HTTP 版本,例如 HTTP/1.1HTTP/2

示例:

GET /index.html HTTP/1.1

这里,GET 是请求方法,/index.html 是请求的资源,HTTP/1.1 是协议版本。

请求头:

请求头包含了客户端与服务器之间的各种信息,例如客户端信息、缓存控制、授权信息等。常见的请求头包括:

  • Host:指定服务器的域名和端口号。
  • User-Agent:指定发送请求的浏览器或客户端软件的详细信息。
  • Accept:指定客户端能接受的内容类型(如 text/htmlapplication/json)。
  • Content-type:指定请求体的内容类型,通常在 POSTPUT 请求中使用。
  • Authorization: 如果请求需要身份验证,包含认证信息。

空行:

请求头和请求体之间有一个空行,用于分隔请求头和请求体。空行是必须的,表示头部字段的结束。

消息体:

请求体仅在某些请求方法中使用(如 POSTPUTPATCH)。它包含了要发送的数据,通常用于提交表单、上传文件或发送 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.1HTTP/2)。
  • 状态码(如 200404)。
  • 状态描述(例如 OKNot Found)。

响应头:

响应头包含了多种元信息,描述服务器和返回的数据。常见的响应头字段包括:

  • Content-Type:响应体的内容类型(如 text/htmlapplication/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 的角色。

Pasted image 20240516180621.png

创建 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 项目,并为其添加虚拟环境。

Pasted image 20240516204030.png

如上图所示,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应用程序或框架之间的一种简单而通用的接口”。

该项目目录添加解释器环境,创建虚拟环境的界面如下图所示:

Pasted image 20240516231559.png

安装项目依赖项

方法一:在 Pycharm 的偏好设置中,找到该项目的解释器环境和已经安装的三方库页面:可以通过点击添加(+)按钮来安装新的依赖项,安装 Django 依赖项时,需要指定版本号,否则将默认安装更新最新的版本。

Pasted image 20240516232427.png

方法二: 打开 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)

Pasted image 20240516220844.png

Pasted image 20240516221523.png

方法二:在 Run 菜单选择 Edit Configuration,配置 Django server 运行项目(适用于专业版 PyCharm)。

方法三:在 PyCharm 的终端(Terminal)中通过命令运行项目(适用于专业版和社区版 PyCharm)。

(venv) PS D:\PycharmProjects\helloDjango> python manage.py runserver

查看运行效果

在浏览器中输入http://127.0.0.1:8000访问我们的服务器,效果如下图所示。

Pasted image 20240516214508.png 说明:

  • 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'

直接刷新刚才的页面,可以看到修改显示语言和时区的效果。 Pasted image 20240516234333.png

创建 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/。页面效果如下:

Pasted image 20240517023601.png

我们通过上面代码在浏览器生成了内容,但目前还只是静态内容。

渲染动态网页

如果想要在网页上渲染动态内容,可以修改 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)

刷新页面检查

刷新页面查看程序的运行结果,预期每刷新一次网页,可以看到不一样的内容。 Pasted image 20240517112904.png

使用模板页

因为在实际项目中的前端页面往往非常复杂,如上述手动拼接 HTML 代码显然不可取。为此,Django 提供了模板页(MTV 模式中的 T)。

模版页中使用占位符和指令来动态渲染数据,简化了动态内容生成的问题。通过使用模板页,可以更高效地构建复杂的前端页面,使开发流程更直观。

在 Django 中,通过 render 函数渲染模板,模板引擎(如 Django 的模板系统)将动态数据与静态模板结合,生成完整的 HTML 文件并返回给客户端。这里的渲染是后端渲染,即在服务器段完成页面的渲染再输出到浏览器中。

后端渲染的做法在 Web 应用的访问量较大时,会使服务器承受较大的负担,所以越来越多的 Web 应用会选择前端渲染的方式,即服务器只提供页面所需要的数据(通常为 JSON 格式数据),在浏览器通过 JavaScript 代码获取这些数据并渲染页面上。

关于前端渲染的内容,后续学习[[前后端分离开发入门]]

使用模板页的操作步骤:

创建模板页文件夹

在项目目录下创建名为 templates 文件夹:

Pasted image 20240517123227.png 说明:将定义的页面放置在 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'), ]:在列表的最后加上一个逗号 ,,即使只有一个元素,也能确保这个元素被识别为列表中的单一元素。

运行项目

重新运行项目验证结果。

参考

Django 官方文档

HTTP 响应状态码

本文由作者按照 CC BY 4.0 进行授权。