How-To's Web Development

Django 视图简介

Read this post in other languages:

视图是 Django 架构模式的核心,理解视图对所有使用该框架的开发者来说都至关重要。 如果您是刚开始使用 Django 开发 Web 应用,或者只是想复习一下视图的相关知识,本文可以满足您的需求。 

深入理解视图将有帮助您在 Django 项目中更快取得进展。 无论您是在处理 API 后端还是 Web UI 流程,了解如何使用视图都至关重要。

本文将讲解什么是 Django 视图、视图的不同类型、最佳做法以及用例。

什么是 Django 视图?

视图是 Django 的 MTV(模型-模板-视图)架构模式的核心组件。 它们本质上充当模型模板之间的中间人,处理用户请求并返回响应。

您可能在 MVC(模型-视图-控制器)模式中接触过视图。 不过,这些视图与 Django 中的视图略有不同,不能完全对应。 Django 视图本质上是 MVC 中的控制器,而 Django 模板与 MVC 中的视图大致相同。 因此,即使您已经熟悉 MVC 环境中的视图,您也应该理解 Django 视图的细微差别。

视图在 Django 中是用户界面的一部分,它们处理向 Django 赋能应用和网站发出的 Web 请求的逻辑和数据处理。 它们将模板呈现为用户查看网页时所看到的内容。 每个基于函数或类的视图都会接收用户请求,从其模型中获取数据,应用业务逻辑或数据处理,然后准备并向模板返回 HTTP 响应。

此响应可以是 Web 浏览器显示的任何内容,一般是 HTML 网页。 不过,Django 视图也可以返回图像、XML 文档、重定向、错误页面等。

呈现数据并将数据传递到模板

Django 提供了 render() 快捷方式,帮助简化视图内部的模板呈现。 使用 render() 有助于避免手动加载模板和创建响应的繁琐步骤。

PyCharm 提供了智能代码补全,当您在视图中开始输入时,它会自动建议 django.shortcuts 中的 render() 函数。 它还可以识别模板名称并为模板路径提供自动补全,帮助您避免拼写错误和其他错误。

用户提供请求、模板名称和上下文字典,这些会为模板提供数据。 获得必要数据后,视图会将其传递给模板,数据将在模板中呈现给用户。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
from django.shortcuts import render
def my_view(request):
# Some business logic to obtain data
data_to_pass = {'variable1': 'value1', 'variable2': 'value2'}
# Pass the data to the template
return render(request, 'my_template.html', context=data_to_pass)
from django.shortcuts import render def my_view(request): # Some business logic to obtain data data_to_pass = {'variable1': 'value1', 'variable2': 'value2'} # Pass the data to the template return render(request, 'my_template.html', context=data_to_pass)
from django.shortcuts import render

def my_view(request):
    # Some business logic to obtain data
    data_to_pass = {'variable1': 'value1', 'variable2': 'value2'}

    # Pass the data to the template
    return render(request, 'my_template.html', context=data_to_pass)

在本例中,data_to_pass 是一个字典,其中包含要发送到模板的数据。 然后,使用 render 函数通过提供的上下文数据呈现模板 (my_template.html)。

现在,您可以在模板 (my_template.html) 中访问和显示数据。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
    

{{ variable1 }}

{{ variable2 }}

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter

在模板中,使用双大括号 ({{ }}) 表示模板变量。 它们将被替换为视图传递的上下文数据中的值。

PyCharm 为 Django 模板标记、变量和循环提供了补全和语法高亮显示。 它还提供了针对常见错误的编辑器内 Lint 分析。 这样,您就可以专注于构建视图和处理逻辑,而不是花时间手动填写模板元素或调试常见错误。

PyCharm Django 补全

基于函数的视图

Django 有两种视图:基于函数的视图和基于类的视图。

基于函数的视图使用简单的 Python 函数构建,通常分为四个基本类别:创建、读取、更新和删除 (CRUD)。 这是开发中任何框架的基础。 它们接收 HTTP 请求并返回 HTTP 响应。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
from django.http import HttpResponse
def my_view(request):
# View logic goes here
context = {"message": "Hello world"}
return HttpResponse(render(request, "mytemplate.html", context))
from django.http import HttpResponse def my_view(request): # View logic goes here context = {"message": "Hello world"} return HttpResponse(render(request, "mytemplate.html", context))
from django.http import HttpResponse

def my_view(request):

    # View logic goes here
    context = {"message": "Hello world"}

    return HttpResponse(render(request, "mytemplate.html", context))

这段代码处理视图的逻辑,准备一个上下文字典以将数据传递给呈现的模板,并在响应对象中返回最终模板 HTML。

基于函数的视图简单直接。 逻辑包含在单个 Python 函数中,而不是分散在类的各个方法中,因此最适合处理量小的用例。

借助 PyCharm,您可以使用实时模板自动生成 def my_view(request) 结构。 实时模板是预定义的代码段,可以扩展为样板代码。 此功能可以节省时间并确保视图定义具有一致的结构。

⌘J、输入 Listview,然后按 Tab 键即可调用实时模板。 

此外,PyCharm 还包含 Django Structure(Django 结构)工具窗口,显示 Django 项目中所有视图的列表(按应用组织)。 由此,您可以快速找到视图、在视图之间导航,以及确认每个视图属于哪个文件。

基于类的视图

Django 引入了基于类的视图,用户不需要重复编写相同的代码。 它们不会取代基于函数的视图,而是具有特定应用和优势,尤其是在需要复杂逻辑的情况下。

Django 中基于类的视图提供了可重用的父类,后者负责实现 Web 应用程序视图通常需要的各种模式和功能。 您可以从这些父类中获取视图,减少样板代码。 

基于类的视图提供泛型父类,例如:

  • ListView
  • DetailView
  • CreateView
  • 等等。

下面是两个类似的代码段,演示了一个简单的 BookListView。第一个代码段展示了使用基于类的默认约定的基本实现,第二个代码段解释了如何通过指定额外形参自定义视图。 

基本实现: 

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
from django.views.generic import ListView
from .models import Book
class BookListView(ListView):
model = Book
# The template_name is omitted because Django defaults to 'book_list.html'
# based on the convention of _list.html for ListView.
from django.views.generic import ListView from .models import Book class BookListView(ListView): model = Book # The template_name is omitted because Django defaults to 'book_list.html' # based on the convention of _list.html for ListView.
from django.views.generic import ListView
from .models import Book 

class BookListView(ListView):
    model = Book
    # The template_name is omitted because Django defaults to 'book_list.html' 
    # based on the convention of _list.html for ListView.

BookListView 呈现后,它会自动查询 Book 记录并在呈现 book_list.html 时将其传递给变量 books。 这意味着您可以快速创建视图来列出对象,无需重写底层逻辑。

自定义实现

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
from django.views.generic import ListView
from .models import Book
class BookListView(ListView):
model = Book
# You can customize the view further by adding additional attributes or methods
def get_queryset(self):
# Example of customizing the queryset to filter books
return Book.objects.filter(is_available=True)
from django.views.generic import ListView from .models import Book class BookListView(ListView): model = Book # You can customize the view further by adding additional attributes or methods def get_queryset(self): # Example of customizing the queryset to filter books return Book.objects.filter(is_available=True)
from django.views.generic import ListView
from .models import Book 

class BookListView(ListView):

    model = Book
	# You can customize the view further by adding additional attributes or methods 
    def get_queryset(self):
	# Example of customizing the queryset to filter books
	return Book.objects.filter(is_available=True)

在第二个代码段中,我们引入了自定义 get_queryset() 方法,这让我们可以更精确地筛选视图中显示的记录。 这表明基于类的视图可以在其默认功能外扩展,满足应用程序的需求。 

基于类的视图还定义了与请求和响应生命周期的关键部分相关的方法,例如: 

  • get()GET 请求的逻辑。
  • post()POST 请求的逻辑。
  • dispatch() – 决定调用 get()post() 的方法。

这些类型的视图提供了结构,同时还能根据需要自定义,非常适合复杂的用例。

PyCharm 为 ListViewDetailViewTemplateView 等基于类的视图提供了实时模板,您可以在几秒内生成整个视图类,附带样板方法和 docstring。

PyCharm 中的 Django 实时模板

创建自定义基于类的视图

您还可以将 Django 的泛型视图类子类化并根据需要自定义,创建自己的视图类。 

您可能需要创建自己的类的用例包括:

  • 添加业务逻辑,例如复杂的计算。
  • 混合多个泛型父级来融合功能。
  • 管理跨多个请求的会话或状态。
  • 使用自定义查询优化数据库访问。 
  • 在不同区域重用通用呈现逻辑。 

自定义基于类的视图可能如下所示:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
from django.views.generic import View
from django.shortcuts import render
from . import models
class ProductSalesView(View):
def get(self, request):
# Custom data processing
sales = get_sales_data()
return render(request, "sales.html", {"sales": sales})
def post(self, request):
# Custom form handling
form = SalesSearchForm(request.POST)
if form.is_valid():
results = models.Sale.objects.filter(date__gte=form.cleaned_data['start_date'])
context = {"results": results}
return render(request, "search_results.html", context)
# Invalid form handling
errors = form.errors
return render(request, "sales.html", {"errors": errors})
from django.views.generic import View from django.shortcuts import render from . import models class ProductSalesView(View): def get(self, request): # Custom data processing sales = get_sales_data() return render(request, "sales.html", {"sales": sales}) def post(self, request): # Custom form handling form = SalesSearchForm(request.POST) if form.is_valid(): results = models.Sale.objects.filter(date__gte=form.cleaned_data['start_date']) context = {"results": results} return render(request, "search_results.html", context) # Invalid form handling errors = form.errors return render(request, "sales.html", {"errors": errors})
from django.views.generic import View
from django.shortcuts import render
from . import models

class ProductSalesView(View):

    def get(self, request):
     
        # Custom data processing 
        sales = get_sales_data()
        
        return render(request, "sales.html", {"sales": sales})

    def post(self, request):

        # Custom form handling
        form = SalesSearchForm(request.POST)  
        if form.is_valid():
            results = models.Sale.objects.filter(date__gte=form.cleaned_data['start_date'])
            context = {"results": results}
            return render(request, "search_results.html", context)
            
        # Invalid form handling
        errors = form.errors
        return render(request, "sales.html", {"errors": errors})

在这里,借助自定义 getpost 处理程序,您可以在请求之间扩展现有内容。

各个视图类型的使用条件

根据视图逻辑的复杂程度和需求,基于函数和基于类的视图都可以发挥作用。 

主要区别在于基于类的视图:

  • 通过子类化和父类继承行为促进重用。
  • 适合请求之间的状态管理。
  • 提供更多结构和强制规范。

您可以将其用于:

  • 具有复杂呈现逻辑的仪表板页面。 
  • 显示动态数据的面向公众的页面。
  • 用于内容管理的管理门户。
  • 涉及数据库模型的列表或详细信息页面。

另一方面,基于函数的视图:

  • 更简单,创建时所需的代码更少。
  • 可以让 Python 开发者更容易掌握。
  • 灵活性高,约束较少。

它们的用例包括: 

  • 对创意进行原型设计。
  • 简单的 CRUD 或数据库视图。
  • 着陆页或营销页面。 
  • 用于为 Web 请求服务的 API 端点。

简而言之,基于函数的视图灵活、直接且更易于推理。 不过,对于较复杂的情况,您需要创建更多无法重用的代码。

Django 中基于类的视图强制结构并且可重用,但理解和实现更具挑战性,也更难调试。

视图和 URL

如前所述,在 Django 中,视图是确定模板呈现方式的函数或类。 每个视图都链接到特定的 URL 模式,将传入请求引导到正确的位置。

理解视图与 URL 之间的关系对于有效管理应用程序流程非常重要。 

每个视图都与 Django 应用的 urls.py 文件中定义的 URL 模式相对应。 这种 URL 映射确保当用户导航到应用程序中的特定地址时,Django 能够准确知道要调用哪个视图。 

我们来看一个简单的 URL 配置: 

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
from django.urls import path
from .views import BookListView
urlpatterns = [
path('books/', BookListView.as_view(), name='book-list'),
]
from django.urls import path from .views import BookListView urlpatterns = [ path('books/', BookListView.as_view(), name='book-list'), ]
from django.urls import path
from .views import BookListView

urlpatterns = [
    path('books/', BookListView.as_view(), name='book-list'),
]

在这种设置中,当用户访问 /books/ 时,BookListView 就会开始呈现书籍列表。 将 URL 清晰映射到视图后,代码库更易阅读,也更整洁。

使用 PyCharm 简化 URL 管理

随着应用程序的成长,Django 中端点的管理和直观呈现可能会变得更具挑战性。 PyCharm 通过 Endpoints(端点)工具窗口解决了这个问题,窗口会集中显示所有应用的 URL 模式、链接视图和 HTTP 方法。 借助此功能,您可以查看项目中每个端点的列表,轻松了解哪些视图与特定 URL 绑定。 

点击一下,您就可以立即找到并导航到相应视图,不再需要在多个 urls.py 文件中搜索。 这尤其适合 URL 配置跨越多个文件的大型 Django 项目,以及团队工作,因为快速建立上下文至关重要。

此外,借助 Endpoints(端点)工具窗口,您可以在表格式界面中直观呈现所有端点。 每一行都会显示 URL 路径、HTTP 方法(GETPOST 等)以及给定端点的关联视图函数或类。 

此功能不仅可以提高工作效率,还可以改善代码导航,让您轻松发现缺失或重复的 URL 模式。 这种可见性对于调试路由问题或让新开发者加入项目来说非常宝贵。

观看这段视频,详细了解 Endpoints(端点)工具窗口以及如何从中受益。 

 

使用 Django 视图的最佳做法

下面的一些指导原则可以帮助您创建结构良好且可维护的视图。

保持视图专注

视图应该专注于处理请求、获取数据、将数据传递给模板,以及控制流程和重定向。 复杂的业务逻辑和复杂的处理应该在其他地方进行,例如在模型方法或专用服务类中。 

不过,您应该注意不要在模型中添加过多逻辑,因为这可能导致 Django 中的“胖模型”反模式。 Django 关于视图的文档提供了有关正确构建视图结构的更多洞察。 

保持视图和模板精简

最好保持视图和模板精简。 视图应负责请求处理和数据检索,而模板应该专注于以最少的逻辑进行展示。

复杂的处理应在模板之外使用 Python 完成,以改进可维护性和测试。 有关详情,请参阅 Django 模板文档

解耦数据库查询

将数据库查询提取到单独的模型管理器或仓库中,而不是直接放在视图中,有助于减少重复。 参阅 Django 模型文档,获取有关有效管理数据库交互的指导。 

尽可能使用基于类的泛型视图

Django 基于类的泛型视图(如 DetailViewListView)提供了可重用性,无需您编写大量代码。 使用它们可以节省时间,让您不必再费心造轮子。 泛型视图文档是理解这些功能的绝佳资源。 

基于函数的视图能够应对简单用例

对于服务 API 这样的基本视图,函数可能比类更有效。 为复杂 UI 流保留基于类的复杂视图。 编写视图文档页面提供了实用示例。

清晰构建路由和 URL 配置结构

按功能将路由和视图处理程序清晰归类到应用中。 这可以简化源的查找和导航。 查看 Django URL 调度程序文档,了解构建 URL 配置结构的最佳做法。 

后续步骤 

现在,您已经对 Django 中的视图有了基本了解,接下来,您可能会想深入探究框架和其他后续步骤。

  • 通过如何学习 Django这篇博文增长您的 Django 知识,这篇文章非常适合初学者或希望巩固专业技能的人员。
  • 探索 Django 现状,了解 Django 开发的最新趋势,获得更多灵感。

PyCharm 中的 Django 支持

PyCharm Professional 是用于 Django 开发的一流 IDE。 借助 Django 特定的编码辅助、项目级导航和重构以及对 Django 模板的全面支持,它可以让您更快地编写代码。 一键连接到您的数据库,并使用 TypeScript、JavaScript 和其他前端框架。 PyCharm 也直接支持 Flask 和 FastAPI。 

创建更好的应用程序并精简代码。 立即开始使用 PyCharm,获得轻松的 Django 开发体验。

本博文英文原作者:

Evgenia Verbina

Evgenia Verbina

image description

Discover more