详解Django的 as_view() 函数:将 Django 视图转换为类视图

  • Post category:Python

Django的as_view()函数是一个将类视图转换为函数视图的工具函数,它将类视图封装为一个可调用对象,这个对象可以处理请求并返回响应。在Django中,大多数视图都是使用类视图方式定义的。但是,在某些场景下(如需要访问视图内的实例属性),使用函数视图会更加方便,因此as_view()函数对于这种情况非常有用。下面是具体的使用方法和实例说明。

使用方法

使用as_view()函数,需要在类视图继承View类的基础上重载get方法或post方法等,具体方法根据开发需求而定。

首先在视图模块中导入as_view()函数:

from django.views.generic import View
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required

class MyView(View):
    template_name = 'my_template.html'

    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        # 处理 GET 请求,返回响应
        ...

    def post(self, request, *args, **kwargs):
        # 处理 POST 请求,返回响应
        ...

my_view = MyView.as_view()

这个例子演示了如何使用 as_view() 将类视图 MyView 转换为函数视图。在调用as_view()方法后,my_view 变量就成为了一个可以响应请求的函数。

通过 as_view() 转换的函数视图,处理了 GET 和 POST 请求后,会返回响应。get()post() 方法中的代码会负责处理请求,并用合适的响应来响应请求。

上面例子中,使用了 method_decorator 装饰器和 login_required 装饰器来添加对用户登录的要求。dispatch() 方法能确保所有的请求都会被 login_required 装饰器要求登录,而且同时可以调用原始的 dispatch() 方法。这个功能通过调用 super().dispatch() 来实现。

示例

实例1:类视图的基本转换

首先,看一个最基本的转换类视图的代码。该类视图可以处理 GET 请求,并将 “Hello, World!” 渲染到模板中。

from django.views.generic import View
from django.http import HttpResponse
from django.shortcuts import render

class HelloWorld(View):
    template_name = 'hello_world.html'

    def get(self, request):
        return render(request, self.template_name, {'message': 'Hello, World!'})

hello_world = HelloWorld.as_view()

这个例子中,如果我们在路由中使用了这个函数视图,那么我们将获得一个可用于处理请求的视图。如下所示:

from django.urls import path

from .views import hello_world


app_name = 'mysite'

urlpatterns = [
    path('hello-world/', hello_world, name='hello_world'),
]

实例2:基于类视图的分页器

下面我们看一个更为复杂的操作。该示例定义了一个应用程序的类视图 ItemList,它获取项目列表,并将其分成 pagesize 块。从 URL 获取当前页数,然后从项目列表中返回该页。

这个示例演示了如何在类视图中使用 Paginator 类,并让 as_view() 函数处理请求。

from django.views.generic import View
from django.shortcuts import render
from django.core.paginator import Paginator


class ItemList(View):
    template_name = 'item_list.html'
    queryset = range(200)       # 生成 200 个数据
    paginate_by = 20            # 每页显示 20 条数据

    def get(self, request):
        paginator = Paginator(self.queryset, self.paginate_by)

        page = request.GET.get('page')
        items = paginator.get_page(page)

        return render(request, self.template_name, {'items': items})


item_list = ItemList.as_view()

类视图定义了一个 queryset,其中包含多个项目,我们使用Paginator对象将这些项目分成大小为 paginate_by的页面。视图使用GET参数 page来选择页码。如果用户不输入页码,将默认为页面的第一页。

在视图中,我们使用 Paginator 对象来获取指定页码 page 中的数据,然后将其中的每个项目传递给模板。模板将负责在当前页面上显示它们。