DRF視圖詳解:從基礎視圖到通用視圖實踐指南
一、基礎視圖 (APIView)
APIView 是 DRF 中所有視圖的基類,繼承自 Django 的 View,并添加了 DRF 特有的功能(如認證、權限、限流等)。
示例:使用APIView實現“增刪改查查”
from rest_framework.views import APIView
from rest_framework import serializers
from rest_framework.response import Response
from rest_framework import generics
class ShopSerializer(serializers.ModelSerializer):
class Meta:
model = ShopModel
fields = ["id", "username", "title", "description"]
class ShopView(APIView):
# 查列表
def get(self, request):
shops = ShopModel.objects.all()
serializer = ShopSerializer(instance=shops, many=True)
return Response(serializer.data)
# 增
def post(self, request):
serializer = ShopSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors)
class ShopDetailView(APIView):
# 查單個
def get(self, request, pk):
shop = ShopModel.objects.get(pk=pk)
serializer = ShopSerializer(instance=shop)
return Response(serializer.data)
# 刪
def delete(self, request, pk):
ShopModel.objects.get(pk=pk).delete()
return Response()
# 改
def put(self, request, pk):
shop = ShopModel.objects.get(pk=pk)
serializer = ShopSerializer(instance=shop, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors)
配置路由:urls.py
from django.urls import path
from .views import ShopView, ShopDetailView
urlpatterns = [
path("shops/", ShopView.as_view()),
path("shops/<int:pk>/", ShopDetailView.as_view()),
]
這種方式雖然直觀,但存在大量重復代碼(如查詢集獲取、序列化器實例化等)。為了解決這個問題,DRF 提供了通用視圖。
二、通用視圖 (Generic Views)
DRF 的通用視圖基于 "Mixin 組合" 思想,將常用功能封裝成可復用的組件,通過繼承組合實現復雜功能。通用視圖的核心是 GenericAPIView,它提供了基礎的查詢集和序列化器管理功能。
常用通用視圖
ListAPIView:獲取列表數據(GET)CreateAPIView:創建數據(POST)RetrieveAPIView:獲取單個數據(GET)UpdateAPIView:更新數據(PUT/PATCH)DestroyAPIView:刪除數據(DELETE)- 組合視圖:
ListCreateAPIView、RetrieveUpdateAPIView等
通用視圖示例:學生信息管理
步驟 1:定義模型
# models.py
from django.db import models
class Student(models.Model):
name = models.CharField(max_length=255, verbose_name="姓名")
age = models.IntegerField(verbose_name="年齡")
gender = models.CharField(max_length=255, verbose_name="性別")
class Meta:
db_table = "student"
verbose_name = "學生表"
步驟 2:創建序列化器
# serializers.py
from rest_framework import serializers
from .models import Student
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = "__all__"
步驟 3:實現通用視圖
# views.py
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
from .models import Student
from .serializers import StudentSerializer
# 查列表、增 視圖
class StudentListCreate(ListCreateAPIView):
queryset = Student.objects.all()
serializer_class = StudentSerializer
# 查單個、刪、改 視圖
class StudentRetrieveUpdateDestroy(RetrieveUpdateDestroyAPIView):
queryset = Student.objects.all()
serializer_class = StudentSerializer
步驟 4:配置 URL
# urls.py
from django.urls import path
from .views import StudentListCreate, StudentRetrieveUpdateDestroy
urlpatterns = [
path("api/students/", StudentListCreate.as_view()),
path("api/students/<int:pk>/", StudentRetrieveUpdateDestroy.as_view()),
]
使用通用視圖,實現完整的 CRUD 功能,大大減少了重復代碼。
測試通用視圖
運行Django項目
# 創建管理員賬號
python manage.py createsuperuser --username admin --email admin@example.com
# 運行Django項目
python manage.py runserver 0.0.0.0:8000
打開瀏覽器登錄訪問:http://127.0.0.1:8000/api/books/
- get:查詢列表
- post:新增

打開瀏覽器登錄訪問:http://127.0.0.1:8000/api/books/1
- get:查詢單個對象
- put:修改
- delete:刪除

三、通用視圖的高級用法
動態查詢集
通過重寫 get_queryset() 方法,可以實現動態過濾查詢集,例如只返回當前登錄用戶的數據:
def get_queryset(self):
# 只返回當前用戶創建的數據
return Student.objects.filter(created_by=self.request.user)
多字段查詢
默認情況下,通用視圖通過 pk 字段查詢單個對象。如果需要支持多字段查詢,可以自定義 Mixin 類:
from django.shortcuts import get_object_or_404
class MultipleFieldLookupMixin:
"""支持多字段查詢的 Mixin"""
def get_object(self):
queryset = self.get_queryset()
queryset = self.filter_queryset(queryset)
filter_conditions = {}
# 遍歷 lookup_fields 構建查詢條件
for field in self.lookup_fields:
if self.kwargs.get(field):
filter_conditions[field] = self.kwargs[field]
return get_object_or_404(queryset, **filter_conditions)
使用示例:
class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
lookup_fields = ['account', 'username'] # 支持通過 account 或 username 查詢
自定義權限和認證
通過設置 permission_classes 和 authentication_classes 屬性,可以為視圖添加權限和認證控制:
from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import TokenAuthentication
class UserProfileView(RetrieveAPIView):
serializer_class = UserSerializer
# 只允許已認證用戶訪問
permission_classes = [IsAuthenticated]
# 使用 Token 認證
authentication_classes = [TokenAuthentication]
def get_object(self):
# 返回當前登錄用戶信息
return self.request.user
四、GenericAPIView類深度解析
GenericAPIView 是 DRF 視圖系統的核心抽象,它通過標準化的屬性和方法,簡化了數據查詢、序列化和過濾等常見操作。通過與 Mixin 類結合,GenericAPIView 能夠快速實現 CRUD 功能,同時保留了足夠的靈活性,允許開發者通過重寫方法定制業務邏輯。
類繼承關系
GenericAPIView 是 DRF 通用視圖體系的基石,其繼承關系如下
- 作為
APIView的子類,GenericAPIView保留了請求處理、認證、權限、限流等基礎功能 GenericAPIView新增了對查詢集(QuerySet)和序列化器(Serializer)的標準化管理,為數據操作提供了統一接口

核心類屬性
GenericAPIView 通過類屬性定義了視圖的核心配置,這些屬性決定了視圖如何獲取數據、如何序列化數據以及如何處理查詢參數。
| 屬性名 | 說明 |
|---|---|
queryset |
視圖使用的基礎查詢集,用于獲取模型實例。通常需要設置此屬性或重寫 get_queryset() 方法。注意直接訪問 self.queryset 會導致結果緩存,應優先使用 get_queryset() 方法。 |
serializer_class |
用于數據驗證、序列化和反序列化的序列化器類。需設置此屬性或重寫 get_serializer_class() 方法。 |
lookup_field |
用于查詢單個對象的模型字段,默認值為 'pk'(主鍵)。若使用自定義字段,需確保視圖和序列化器同步設置。 |
lookup_url_kwarg |
URL 中用于對象查找的關鍵字參數,默認與 lookup_field 相同。需與 URL 配置中的參數名保持一致。 |
pagination_class |
列表數據的分頁類,默認使用全局配置 DEFAULT_PAGINATION_CLASS。設置為 None 可禁用分頁。 |
filter_backends |
用于過濾查詢集的后端類列表,默認使用全局配置 DEFAULT_FILTER_BACKENDS。 |
常用類方法
GenericAPIView 提供了一系列方法用于處理查詢集、對象實例和序列化器,這些方法是構建數據交互邏輯的核心。
數據查詢相關方法
- get_queryset(self):返回視圖使用的查詢集,是獲取數據的主要入口。默認返回 queryset 屬性定義的查詢集,可重寫以實現動態過濾(如返回當前用戶的數據)
def get_queryset(self):
return self.request.user.articles.all() # 僅返回當前用戶發布的文章
- get_object(self):返回詳細視圖所需的單個對象實例。默認通過 lookup_field 從查詢集中過濾對象,可重寫以實現復雜查詢邏輯(如多字段聯合查詢)。
- filter_queryset(self, queryset):應用過濾后端對查詢集進行過濾,返回處理后的查詢集。可通過重寫自定義過濾邏輯
def filter_queryset(self, queryset):
# 根據請求參數動態選擇過濾后端
if 'category' in self.request.query_params:
queryset = queryset.filter(category=self.request.query_params['category'])
return queryset
序列化器相關方法
- get_serializer_class(self):返回當前視圖使用的序列化器類,默認返回 serializer_class 屬性。可重寫以根據條件返回不同的序列化器
def get_serializer_class(self):
if self.request.method == 'GET':
return ReadOnlyArticleSerializer # 只讀場景使用簡化序列化器
return ArticleSerializer # 寫操作使用完整序列化器
- get_serializer(self, instance=None, data=None, many=False, partial=False):返回序列化器實例,自動注入請求上下文(如 request、view)。通常無需重寫,直接調用即可
serializer = self.get_serializer(instance=article, data=request.data)
鉤子方法(與 Mixin 配合)
GenericAPIView 本身不直接實現 CRUD 操作,而是通過與 Mixin 類(如 CreateModelMixin、UpdateModelMixin)結合實現完整功能。這些 Mixin 提供了以下鉤子方法,用于定制對象的保存和刪除行為
| 方法名 | 所屬 Mixin | 說明 |
|---|---|---|
perform_create(self, serializer) |
CreateModelMixin |
創建對象時調用,可用于添加額外字段(如設置創建者): def perform_create(self, serializer): serializer.save(author=self.request.user) |
perform_update(self, serializer) |
UpdateModelMixin |
更新對象時調用,可用于記錄更新時間等: def perform_update(self, serializer): serializer.save(updated_at=timezone.now()) |
perform_destroy(self, instance) |
DestroyModelMixin |
刪除對象時調用,可用于執行額外清理操作: def perform_destroy(self, instance): instance.comments.all().delete() instance.delete() |
其他實用方法
以下方法通常無需重寫
get_serializer_context(self):返回序列化器的上下文字典,默認包含request、view、format信息,可用于在序列化器中訪問請求數據。paginate_queryset(self, queryset):對查詢集進行分頁處理,返回頁面對象或None(若未配置分頁)。get_paginated_response(self, data):返回分頁格式的響應對象,配合分頁功能使用。
您正在閱讀的是《Django從入門到實戰》專欄!關注不迷路~

在 Django REST Framework (DRF) 開發中,視圖是處理 HTTP 請求并返回響應的核心組件。DRF 提供了多種視圖類型,從基礎的 APIView 到功能豐富的通用視圖。本文將詳細介紹視圖的演進過程,幫助理解不同視圖的設計思想和使用方法。
浙公網安備 33010602011771號