Django 介绍

在这篇关于 Django 的首篇文章中,我们将回答“Django 是什么?”这个问题,并概述这个 Web 框架的独特之处。

我们将概述其主要特性,包括一些在本模块中我们没有时间详细介绍的高级功能。我们还将向您展示 Django 应用程序的一些主要构建块(尽管此时您还没有可供测试的开发环境)。

预备知识 服务器端网站编程,特别是网站中客户端-服务器交互机制的总体理解。
目标 熟悉 Django 是什么、它提供了哪些功能以及 Django 应用程序的主要构建块。

Django 是什么?

Django 是一个高级 Python Web 框架,可以实现安全且可维护网站的快速开发。由经验丰富的开发人员构建,Django 解决了 Web 开发中的大部分繁琐工作,因此您可以专注于编写应用程序,而无需重复造轮子。它是免费和开源的,拥有一个蓬勃发展的活跃社区,出色的文档,以及许多免费和付费支持选项。

Django 帮助您编写的软件具备以下特点:

完整

Django 遵循“内含电池”的理念,几乎提供了开发人员“开箱即用”所需的一切。因为您需要的一切都是同一“产品”的一部分,所以它们无缝协作,遵循一致的设计原则,并拥有广泛且最新的文档

多功能

Django 可以(并且已经)用于构建几乎任何类型的网站——从内容管理系统和维基,到社交网络和新闻网站。它可以与任何客户端框架一起工作,并可以以几乎任何格式(包括 HTML、RSS 提要、JSON 和 XML)提供内容。

在内部,虽然它为几乎所有您可能需要的功能提供了选择(例如,几个流行的数据库、模板引擎等),但如果需要,它也可以扩展以使用其他组件。

安全

Django 通过提供一个旨在“正确行事”以自动保护网站的框架,帮助开发人员避免许多常见的安全错误。例如,Django 提供了一种安全的方式来管理用户帐户和密码,避免了将会话信息放入容易受到攻击的 Cookie 中(相反,Cookie 只包含一个密钥,实际数据存储在数据库中)或直接存储密码而不是密码哈希等常见错误。

密码哈希是通过将密码发送到加密哈希函数创建的固定长度值。Django 可以通过运行哈希函数并将其输出与存储的哈希值进行比较来检查输入的密码是否正确。但是,由于该函数的“单向”特性,即使存储的哈希值被泄露,攻击者也很难推断出原始密码。

Django 默认提供对许多漏洞的保护,包括 SQL 注入、跨站脚本、跨站请求伪造和点击劫持(有关此类攻击的更多详细信息,请参阅网站安全)。

可伸缩

Django 使用基于组件的“无共享”架构(架构的每个部分都独立于其他部分,因此可以在需要时替换或更改)。不同部分之间清晰的分离意味着它可以通过在任何级别添加硬件来扩展以应对增加的流量:缓存服务器、数据库服务器或应用程序服务器。一些最繁忙的站点已成功扩展 Django 以满足其需求(例如,Instagram 和 Disqus,仅举两例)。

可维护

Django 代码是使用鼓励创建可维护和可重用代码的设计原则和模式编写的。特别是,它利用了“不重复自己”(DRY)原则,因此没有不必要的重复,从而减少了代码量。Django 还提倡将相关功能分组到可重用的“应用程序”中,并在更低的级别上,将相关代码分组到模块中(遵循模型-视图-控制器 (MVC) 模式)。

可移植

Django 是用 Python 编写的,Python 可以在许多平台上运行。这意味着您不受任何特定服务器平台的限制,可以在多种 Linux、Windows 和 macOS 版本上运行您的应用程序。此外,Django 得到了许多 Web 主机提供商的良好支持,他们通常为托管 Django 站点提供特定的基础设施和文档。

它从何而来?

Django 最初由一个负责创建和维护报纸网站的 Web 团队在 2003 年至 2005 年间开发。在创建了许多网站之后,该团队开始提取和重用许多通用代码和设计模式。这些通用代码演变为一个通用的 Web 开发框架,并于 2005 年 7 月作为“Django”项目开源。

Django 不断发展和改进,从 2008 年 9 月的第一个里程碑版本 (1.0) 到 2023 年底的 5.0 版本。每个版本都增加了新功能和错误修复,从支持新型数据库、模板引擎和缓存,到添加“通用”视图函数和类(这减少了开发人员在许多编程任务中必须编写的代码量)。

注意:查看 Django 网站上的发布说明,了解最新版本中的变化,以及为使 Django 变得更好所做的工作量。

Django 现在是一个蓬勃发展的、协作式的开源项目,拥有数以千计的用户和贡献者。虽然它仍然保留了一些反映其起源的特性,但 Django 已经发展成为一个多功能框架,能够开发任何类型的网站。

没有现成且明确的服务器端框架流行度衡量标准(尽管您可以使用计算每个平台的 GitHub 项目数量和 Stack Overflow 问题数量等机制来估计流行度)。一个更好的问题是 Django 是否“足够流行”以避免不受欢迎平台的问题。它是否还在不断发展?如果您需要帮助,能得到吗?如果您学习 Django,是否有机会获得有偿工作?

根据使用 Django 的知名网站数量、代码库贡献者数量以及提供免费和付费支持的人数,是的,Django 是一个流行的框架!

使用 Django 的知名网站包括:Disqus、Instagram、Knight Foundation、MacArthur Foundation、Mozilla、National Geographic、Open Knowledge Foundation、Pinterest 和 Open Stack(来源:Django 概览页面)。

Django 是有主见的吗?

Web 框架通常将自己称为“有主见的”或“无主见的”。

有主见的框架是对如何处理任何特定任务有“正确方法”的框架。它们通常支持特定领域(解决特定类型问题)的快速开发,因为做任何事情的正确方法通常是众所周知且有详细文档的。然而,它们在解决其主要领域之外的问题时灵活性较差,并且倾向于提供较少的组件和方法选择。

相比之下,无主见的框架对如何将组件组合起来以实现目标,甚至应该使用哪些组件,限制要少得多。它们使开发人员更容易使用最合适的工具来完成特定任务,尽管代价是您需要自己找到这些组件。

Django 是“有点主见的”,因此它提供了“两全其美”的优点。它提供了一组组件来处理大多数 Web 开发任务,以及一种(或两种)首选的使用方式。然而,Django 的解耦架构意味着您通常可以从许多不同的选项中进行选择,或者如果需要,可以添加对全新选项的支持。

Django 代码是什么样子的?

在传统的基于数据的网站中,Web 应用程序等待来自 Web 浏览器(或其他客户端)的 HTTP 请求。当收到请求时,应用程序会根据 URL 以及 POST 数据或 GET 数据中的信息来确定所需的内容。根据所需内容,它可能会从数据库中读取或写入信息,或执行满足请求所需的其他任务。然后,应用程序会向 Web 浏览器返回响应,通常通过将检索到的数据插入到 HTML 模板中的占位符来动态创建要由浏览器显示的 HTML 页面。

Django Web 应用程序通常将处理每个步骤的代码分组到单独的文件中

Django - files for views, model, URLs, template

  • URL: 虽然可以通过单个函数处理每个 URL 的请求,但编写一个单独的视图函数来处理每个资源更易于维护。URL 映射器用于根据请求 URL 将 HTTP 请求重定向到适当的视图。URL 映射器还可以匹配 URL 中出现的特定字符串或数字模式,并将这些作为数据传递给视图函数。
  • 视图: 视图是一个请求处理函数,它接收 HTTP 请求并返回 HTTP 响应。视图通过模型访问满足请求所需的数据,并将响应的格式化委托给模板
  • 模型: 模型是 Python 对象,它定义了应用程序数据结构,并提供了管理(添加、修改、删除)和查询数据库中记录的机制。
  • 模板: 模板是定义文件(如 HTML 页面)结构或布局的文本文件,其中包含用于表示实际内容的占位符。视图可以使用 HTML 模板动态创建 HTML 页面,并用来自模型的数据填充它。模板可以用于定义任何类型文件的结构;它不一定是 HTML!

注意: Django 将这种组织方式称为“模型-视图-模板 (MVT)”架构。它与更熟悉的模型-视图-控制器架构有许多相似之处。

下面的部分将让您了解 Django 应用程序这些主要部分的样子(我们将在课程后期,设置好开发环境后,详细介绍)。

将请求发送到正确的视图 (urls.py)

URL 映射器通常存储在名为 urls.py 的文件中。在下面的示例中,映射器 (urlpatterns) 定义了路由(特定的 URL 模式)和相应视图函数之间的一系列映射。如果收到与指定模式匹配的 URL 的 HTTP 请求,则将调用关联的视图函数并传递请求。

python
urlpatterns = [
    path('admin/', admin.site.urls),
    path('book/<int:id>/', views.book_detail, name='book_detail'),
    path('catalog/', include('catalog.urls')),
    re_path(r'^([0-9]+)/$', views.best),
]

urlpatterns 对象是 path() 和/或 re_path() 函数的列表(Python 列表使用方括号定义,其中项目用逗号分隔,并且可能有一个可选的尾随逗号。例如:[item1, item2, item3,])。

这两种方法的第一个参数是要匹配的路由(模式)。path() 方法使用尖括号定义 URL 中将被捕获并作为命名参数传递给视图函数的部分。re_path() 函数使用一种灵活的模式匹配方法,称为正则表达式。我们将在后面的文章中讨论这些!

第二个参数是模式匹配时将调用的另一个函数。符号 views.book_detail 表示该函数名为 book_detail(),并且可以在名为 views 的模块中找到(即,在一个名为 views.py 的文件中)。

处理请求 (views.py)

视图是 Web 应用程序的核心,它接收来自 Web 客户端的 HTTP 请求并返回 HTTP 响应。在此期间,它们调度框架的其他资源来访问数据库、渲染模板等。

下面的示例展示了一个最小的视图函数 index(),它可能由我们上一节中的 URL 映射器调用。像所有视图函数一样,它接收一个 HttpRequest 对象作为参数 (request) 并返回一个 HttpResponse 对象。在这种情况下,我们不对请求做任何操作,并且我们的响应返回一个硬编码的字符串。我们将在后面的部分中向您展示一个执行更有趣操作的请求。

python
# filename: views.py (Django view functions)

from django.http import HttpResponse

def index(request):
    # Get an HttpRequest - the request parameter
    # perform operations using information from the request.
    # Return HttpResponse
    return HttpResponse('Hello from Django!')

注意:一点 Python 知识

  • Python 模块是函数的“库”,存储在单独的文件中,我们可能希望在代码中使用它们。这里我们只从 django.http 模块导入 HttpResponse 对象,以便我们可以在视图中使用它:from django.http import HttpResponse。还有其他方法可以导入模块中的部分或所有对象。
  • 函数使用 def 关键字声明,如上所示,函数名称后括号中列出了命名参数;整行以冒号结尾。请注意,接下来的行都是缩进的。缩进很重要,因为它指定了代码行位于该特定块中(强制缩进是 Python 的一个关键特性,也是 Python 代码如此易读的一个原因)。

视图通常存储在名为 views.py 的文件中。

定义数据模型 (models.py)

Django Web 应用程序通过称为模型的 Python 对象管理和查询数据。模型定义了存储数据的结构,包括字段类型,还可能包括它们的最大大小、默认值、选择列表选项、文档帮助文本、表单标签文本等。模型的定义独立于底层数据库——您可以在项目设置中选择其中一个。一旦您选择了要使用的数据库,您就不需要直接与它通信——您只需编写模型结构和其他代码,Django 会为您处理所有与数据库通信的“脏活”。

下面的代码片段展示了一个用于 Team 对象的非常简单的 Django 模型。Team 类派生自 Django 类 models.Model。它将团队名称和团队级别定义为字符字段,并指定每个记录要存储的最大字符数。team_level 可以是多个值中的一个,因此我们将其定义为选择字段,并提供要显示的选择和要存储的数据之间的映射,以及一个默认值。

python
# filename: models.py

from django.db import models

class Team(models.Model):
    team_name = models.CharField(max_length=40)

    TEAM_LEVELS = (
        ('U09', 'Under 09s'),
        ('U10', 'Under 10s'),
        ('U11', 'Under 11s'),
        # …
        # list other team levels
    )
    team_level = models.CharField(max_length=3, choices=TEAM_LEVELS, default='U11')

注意:一点 Python 知识

Python 支持“面向对象编程”,这是一种将代码组织成对象的编程风格,其中包括相关数据和操作该数据的函数。对象还可以继承/扩展/派生自其他对象,允许相关对象之间共享通用行为。在 Python 中,我们使用关键字 class 来定义对象的“蓝图”。我们可以根据类中的模型创建多种特定类型的对象实例

因此,例如,这里我们有一个 Team 类,它派生自 Model 类。这意味着它是一个模型,并将包含模型的所有方法,但我们也可以赋予它自己的特殊功能。在我们的模型中,我们定义了数据库需要存储我们数据所需的字段,并给它们指定了特定的名称。Django 使用这些定义,包括字段名称,来创建底层数据库。

查询数据 (views.py)

Django 模型提供了一个简单的查询 API,用于搜索关联的数据库。它可以同时使用不同的条件(例如,精确匹配、不区分大小写、大于等)匹配多个字段,并支持复杂的语句(例如,您可以指定搜索以“Fr”开头或以“al”结尾的 U11 团队)。

代码片段显示了一个视图函数(资源处理程序),用于显示我们所有的 U09 团队。list_teams = Team.objects.filter(team_level__exact="U09") 行显示了我们如何使用模型查询 API 过滤所有 team_level 字段完全包含文本 U09 的记录(请注意,此条件如何作为参数传递给 filter() 函数,其中字段名和匹配类型由双下划线分隔:team_level__exact)。

python
## filename: views.py

from django.shortcuts import render
from .models import Team

def index(request):
    list_teams = Team.objects.filter(team_level__exact="U09")
    context = {'youngest_teams': list_teams}
    return render(request, '/best/index.html', context)

此函数使用 render() 函数创建发送回浏览器的 HttpResponse。此函数是一个快捷方式;它通过组合指定的 HTML 模板和要插入模板的一些数据(在名为 context 的变量中提供)来创建 HTML 文件。在下一节中,我们将展示模板如何插入数据以创建 HTML。

渲染数据(HTML 模板)

模板系统允许您指定输出文档的结构,使用占位符来表示在生成页面时将填充的数据。模板通常用于创建 HTML,但也可以创建其他类型的文档。Django 开箱即用支持其原生模板系统和另一个流行的 Python 库 Jinja2(如果需要,它也可以支持其他系统)。

代码片段显示了上一节中 render() 函数调用的 HTML 模板可能的样子。此模板是在假定它在渲染时将访问一个名为 youngest_teams 的列表变量的情况下编写的(此变量包含在上面 render() 函数中的 context 变量中)。在 HTML 骨架内部,我们有一个表达式,它首先检查 youngest_teams 变量是否存在,然后在一个 for 循环中迭代它。在每次迭代中,模板将每个团队的 team_name 值显示在一个 <li> 元素中。

django
## filename: best/templates/best/index.html

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Home page</title>
</head>
<body>
  {% if youngest_teams %}
    <ul>
      {% for team in youngest_teams %}
        <li>{{ team.team_name }}</li>
      {% endfor %}
    </ul>
  {% else %}
    <p>No teams are available.</p>
  {% endif %}
</body>
</html>

您还能做什么?

前面的部分展示了您几乎在每个 Web 应用程序中都会使用的主要功能:URL 映射、视图、模型和模板。Django 提供的其他功能包括:

  • 表单:HTML 表单用于收集用户数据以在服务器上进行处理。Django 简化了表单的创建、验证和处理。
  • 用户认证和权限:Django 包含一个强大的用户认证和权限系统,该系统在设计时就考虑到了安全性。
  • 缓存:动态创建内容比提供静态内容计算强度更大(也更慢)。Django 提供了灵活的缓存,因此您可以存储渲染页面的全部或部分,以便除了必要时才重新渲染。
  • 管理站点:当您使用基本骨架创建应用程序时,Django 管理站点默认包含在内。它使站点管理员可以非常轻松地提供管理页面来创建、编辑和查看站点中的任何数据模型。
  • 数据序列化:Django 使您能够轻松地将数据序列化并以 XML 或 JSON 格式提供。这在创建 Web 服务(一个纯粹向其他应用程序或站点提供数据而不显示任何内容的网站)或创建客户端代码处理所有数据渲染的网站时非常有用。

总结

恭喜,您已完成 Django 之旅的第一步!您现在应该了解 Django 的主要优势、其历史以及 Django 应用程序主要部分的粗略样子。您还应该学习了一些关于 Python 编程语言的知识,包括列表、函数和类的语法。

您已经看到了一些实际的 Django 代码,但与客户端代码不同,您需要设置开发环境才能运行它。那是我们的下一步。