未命名

一、接口开发方式分类

1. 函数视图(Function-Based Views)

from rest_framework.decorators import api_view
from rest_framework.response import Response

@api_view(['GET'])
def book_list(request):
    """
    基于函数的书籍列表视图
    """
    books = Book.objects.all()
    serializer = BookSerializer(books, many=True)
    return Response(serializer.data)

@api_view(['POST'])
def create_book(request):
    """
    基于函数的书籍创建视图
    """
    serializer = BookSerializer(data=request.data)
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=201)
    return Response(serializer.errors, status=400)

​特点​​:

  • 简单直接的装饰器语法

  • 适合小型或单一操作的端点

  • 缺乏面向对象的组织结构

2. 基于类的视图(Class-Based Views)

from rest_framework.views import APIView

class BookList(APIView):
    """
    基于APIView的书籍列表视图
    """
    def get(self, request, format=None):
        books = Book.objects.all()
        serializer = BookSerializer(books, many=True)
        return Response(serializer.data)
    
    def post(self, request, format=None):
        serializer = BookSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=201)
        return Response(serializer.errors, status=400)

特点​​:

  • 将HTTP方法分离为独立的方法

  • 提供更好的代码组织和复用性

  • 可以重写get、post、put、patch、delete等方法

3. 通用视图(Generic Views)

from rest_framework import generics

class BookListCreateView(generics.ListCreateAPIView):
    """
    使用通用视图处理书籍列表和创建
    """
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = [permissions.IsAuthenticated]

class BookRetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView):
    """
    处理书籍详情、更新和删除
    """
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    lookup_field = 'isbn'  # 自定义查找字段

DRF通用视图类型​​:

​视图类​

​功能​

​HTTP方法​

ListAPIView

资源列表

GET

CreateAPIView

创建资源

POST

RetrieveAPIView

获取详情

GET

UpdateAPIView

更新资源

PUT/PATCH

DestroyAPIView

删除资源

DELETE

ListCreateAPIView

列表+创建

GET, POST

RetrieveUpdateAPIView

详情+更新

GET, PUT, PATCH

RetrieveDestroyAPIView

详情+删除

GET, DELETE

RetrieveUpdateDestroyAPIView

详情+更新+删除

GET, PUT, PATCH, DELETE

4. 视图集(ViewSets)

from rest_framework import viewsets

class BookViewSet(viewsets.ModelViewSet):
    """
    使用视图集处理所有书籍操作
    """
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = [IsAdminOrReadOnly]
    
    def get_queryset(self):
        """根据参数过滤查询集"""
        author_id = self.request.query_params.get('author_id')
        if author_id:
            return Book.objects.filter(author_id=author_id)
        return super().get_queryset()
    
    @action(detail=True, methods=['post'])
    def publish(self, request, pk=None):
        """发布书籍的自定义操作"""
        book = self.get_object()
        book.publish()
        return Response({'status': 'published'})

视图集类型​​:

​视图集类​

​描述​

​包含操作​

ViewSet

基础视图集

无默认操作

GenericViewSet

通用视图集

核心通用功能

ModelViewSet

完整CRUD操作

list, create, retrieve, update, partial_update, destroy

ReadOnlyModelViewSet

只读操作

list, retrieve

二、路由

1. FBV/CBV/GV

urlpatterns = [
    path('fbv/list/', views.course_detail,name='fbv-list'),
    path('fbv/list2/<int:pk>/', views.course_detail2,name='fbv-list2'),

    # 类视图要使用as_view():
    # as_view()是类视图的入口方法,将类转换为Django可调用的视图函数
    path('cbv/list/',views.CourseListView.as_view(),name='cbv-list'),

    path('gcbv/list/',views.GCourseList.as_view(),name='gcbv-list'),
    path('gcbv/detail/<int:pk>',views.GCourseDetail.as_view(),name='gcbv-list'),
      ]

2. VS

在 Django REST Framework (DRF) 中,路由器是构建 RESTful API 的关键组件,它自动为视图集生成 URL 配置。

路由器类​

​描述​

​特点​

SimpleRouter

基本路由器

标准CRUD路由

DefaultRouter

默认路由器

包含根视图和可选格式后缀

CustomRouter

自定义路由器

扩展或自定义路由行为

本小节的例子均以****有一个 BookViewSet 视图集,包含标准 CRUD 操作和一个自定义动作 mark_as_read为前提。

# register(prefix, viewset, basename=None) 
# prefix不能带/
router.register(r'books', BookViewSet, basename='book')

1. prefix**(必需参数,字符串)**

  • ​作用​​:用于生成URL前缀。

  • ​示例​​:'users',那么生成的URL将类似于/users/(列表视图)和/users/{pk}/(详情视图)。

  • ​注意​​:这个前缀通常是资源名称的复数形式,如'books'、'authors'。

2. viewset**(必需参数,视图集类)**

  • ​作用​​:要注册的视图集类(必须是ViewSet的子类,如ModelViewSet、ReadOnlyModelViewSet或自定义的ViewSet)。

  • ​示例​​:UserViewSet。

3. basename**(可选参数,字符串)**

  • ​作用​​:生成的URL模式名称的前缀(用于reverse反向解析)。

  • ​默认值​​:如果没有提供,将根据queryset属性(如果视图集有设置)或模型名(小写)自动生成。如果自动生成失败,则必须显式提供。

  • ​生成规则​​:自动生成时,使用模型名称的小写形式(如果视图集有queryset属性)。例如,如果queryset是User.objects.all(),那么basename将是'user'(但注意,生成的URL名称会是user-list和user-detail,这里的basename是'user')。

  • ​何时需要显式指定​​:如果视图集没有设置queryset属性,或者你想覆盖默认的名称,则需要提供此参数。

  • ​示例​​:basename='user',那么生成的URL名称将是user-list、user-detail等。

特别说明:basename的自动生成规则

  • 如果视图集设置了queryset属性,则basename = queryset.model._meta.model_name(模型名称的小写,单数形式)。

  • 如果没有设置queryset,必须显式指定basename,否则会抛出ImproperlyConfigured异常。

1. SimpleRouter(基本路由器)

核心特点

  • 最轻量级的路由器实现

  • 只生成基本的 CRUD 路由

  • 不包含额外的元数据端点

  • 适合简单 API 或性能敏感场景

路由规则

  • 为每个视图集生成两条基本路由:

    1. ​列表路由​​:处理集合操作(list/create)

    2. ​详情路由​​:处理单个对象操作(retrieve/update/delete)

  • 不支持格式后缀(如 .json)

  • 不包含 API 根视图

from rest_framework.routers import SimpleRouter
from .views import BookViewSet
from django.urls import path,include

router = SimpleRouter()
router.register(r'books', BookViewSet, basename='book')
urlpatterns = [
    path("",include(router.urls)),
]
'''
# 列表路由
^books/$ 
  - GET: book-list (列表)
  - POST: book-create (创建)

# 详情路由
^books/(?P<pk>[^/.]+)/$ 
  - GET: book-retrieve (详情)
  - PUT: book-update (全量更新)
  - PATCH: book-partial-update (部分更新)
  - DELETE: book-destroy (删除)

# 自定义动作 (detail=True)
^books/(?P<pk>[^/.]+)/mark_as_read/$ 
  - POST: book-mark-as-read (自定义动作)
  
 
# 实际URL示例
http://api.example.com/books/
http://api.example.com/books/1/
http://api.example.com/books/1/mark_as_read/
'''

2. DefaultRouter(默认路由器)

核心特点

  • DRF 的默认路由器

  • 包含 API 根视图(列出所有端点)

  • 支持格式后缀(.json, .api)

  • 提供超链接 API 支持

  • 包含额外的元数据

路由规则

  • 包含 SimpleRouter 的所有功能

  • 额外添加 API 根视图

  • 支持格式后缀(.json, .api 等)

  • 为每个路由生成两个版本(带后缀和不带后缀)

  • 包含超链接关系支持

from rest_framework.routers import DefaultRouter
from .views import BookViewSet
from django.urls import path,include

router = SimpleRouter()
router.register(r'books', BookViewSet, basename='book')
urlpatterns = [
    path("",include(router.urls)),
]

'''
# API 根视图
^$ 
  - GET: api-root (列出所有端点)

# 书籍资源
^books/$ 
  - GET: book-list
  - POST: book-create
^books\.(?P<format>[a-z0-9]+)/?$ 
  - GET: book-list (带格式后缀)
^books/(?P<pk>[^/.]+)/$ 
  - GET: book-retrieve
  - PUT: book-update
  - PATCH: book-partial-update
  - DELETE: book-destroy
^books/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ 
  - GET: book-retrieve (带格式后缀)
^books/(?P<pk>[^/.]+)/mark_as_read/$ 
  - POST: book-mark-as-read
^books/(?P<pk>[^/.]+)/mark_as_read\.(?P<format>[a-z0-9]+)/?$ 
  - POST: book-mark-as-read (带格式后缀)

# 实际URL示例
http://api.example.com/  # API根视图
http://api.example.com/books.json
http://api.example.com/books/1.api
http://api.example.com/authors/
http://api.example.com/authors/1/mark_as_read.json
'''

3. CustomRouter(自定义路由器)

from rest_framework.routers import DefaultRouter, Route
from rest_framework.response import Response
from rest_framework.views import APIView

class StatsView(APIView):
    """自定义统计端点"""
    def get(self, request):
        return Response({"total_books": 1000, "active_books": 750})

class CustomAPIRootView(APIView):
    """自定义API根视图"""
    def get(self, request):
        return Response({
            "message": "欢迎使用图书API",
            "endpoints": {
                "books": reverse('book-list', request=request),
                "authors": reverse('author-list', request=request),
                "stats": reverse('api-stats', request=request)
            }
        })

class CustomBookRouter(DefaultRouter):
    routes = [
        # 标准列表路由
        Route(
            url=r'^books/$',
            mapping={'get': 'list', 'post': 'create'},
            name='book-list',
            detail=False,
            initkwargs={'suffix': 'List'}
        ),
        # 标准详情路由
        Route(
            url=r'^books/(?P<pk>[^/.]+)/$',
            mapping={
                'get': 'retrieve',
                'put': 'update',
                'patch': 'partial_update',
                'delete': 'destroy'
            },
            name='book-detail',
            detail=True,
            initkwargs={'suffix': 'Detail'}
        ),
        # 自定义批量操作
        Route(
            url=r'^books/bulk/$',
            mapping={'post': 'bulk_create', 'delete': 'bulk_delete'},
            name='book-bulk',
            detail=False,
            initkwargs={}
        ),
        # 自定义归档操作
        Route(
            url=r'^books/(?P<pk>[^/.]+)/archive/$',
            mapping={'post': 'archive'},
            name='book-archive',
            detail=True,
            initkwargs={}
        )
    ]
    
    def get_api_root_view(self, api_urls=None):
        return CustomAPIRootView.as_view()
    
    def get_urls(self):
        urls = super().get_urls()
        # 添加统计端点
        urls.append(
            path('stats/', StatsView.as_view(), name='api-stats')
        )
        return urls

# 使用
router = CustomBookRouter()
router.register(r'', BookViewSet)  # 使用空前缀

# 生成路由:
# /books/          - 列表/创建
# /books/bulk/     - 批量操作
# /books/{pk}/     - 详情/更新
# /books/{pk}/archive/ - 归档
# /stats/          - 统计端点

三、ViewSet

在Django REST framework中,ViewSet是一个用于处理一组相关视图的类。它通过提供诸如list, create, retrieve, update, partial_update, destroy等动作(actions)来封装常见的CRUD操作。使用ViewSet可以简化代码,并且与路由器的配合使得URL配置更加简洁。

ViewSet类本身并不提供任何动作(action),而是提供了一些基础方法(如get_object, get_queryset)和可以重写的动作方法。

1. 配置

1. 核心配置

1. queryset

  • ​作用​​:定义视图集操作的数据源

  • ​类型​​:QuerySet

  • ​默认值​​:None

  • 示例​​:

class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()

2. serializer_class

  • ​作用​​:指定默认序列化器

  • ​类型​​:Serializer 类

  • ​默认值​​:None

  • ​示例​​:

class BookViewSet(viewsets.ModelViewSet):
    serializer_class = BookSerializer

3. permission_classes

  • ​作用​​:设置访问权限控制

  • ​类型​​:权限类列表

  • ​默认值​​:[permissions.AllowAny]

  • ​示例​​:

from rest_framework import permissions

class BookViewSet(viewsets.ModelViewSet):
    permission_classes = [permissions.IsAuthenticated]

4. authentication_classes

  • ​作用​​:指定认证类

  • ​类型​​:认证类列表

  • ​默认值​​:[SessionAuthentication, BasicAuthentication]

  • ​示例​​:

from rest_framework.authentication import TokenAuthentication

class BookViewSet(viewsets.ModelViewSet):
    authentication_classes = [TokenAuthentication]

2. 行为控制配置

1. lookup_field

  • ​作用​​:指定对象查找字段(默认为 'pk')

  • ​类型​​:字符串

  • ​默认值​​:'pk'

  • ​示例​​:

class BookViewSet(viewsets.ModelViewSet):
    lookup_field = 'isbn'

2. lookup_url_kwarg

指定 URL 中的查找字段:

class AuthorSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Author
        fields = ['url', 'name']
        extra_kwargs = {
            'url': {
                'view_name': 'author-detail',
                'lookup_field': 'uuid'  # 使用UUID而非ID
            }
        }

3. pagination_class

  • ​作用​​:指定分页类

  • ​类型​​:分页类

  • ​默认值​​:None

  • ​示例​​:

from rest_framework.pagination import PageNumberPagination

class CustomPagination(PageNumberPagination):
    page_size = 20
    
class BookViewSet(viewsets.ModelViewSet):
    pagination_class = CustomPagination

4. ordering_fields

  • ​作用​​:指定可排序字段

  • ​类型​​:字符串列表

  • ​默认值​​:None

  • ​示例​​:

class BookViewSet(viewsets.ModelViewSet):
    ordering_fields = ['title', 'publication_date', 'rating']

5. search_fields

  • ​作用​​:指定可搜索字段

  • ​类型​​:字符串列表

  • ​默认值​​:None

  • ​示例​​:

class BookViewSet(viewsets.ModelViewSet):
    search_fields = ['title', 'author__name', 'description']

2. 自定义动作

如果你需要添加自定义动作(即非标准动作),可以使用@action装饰器。自定义动作可以响应GET、POST等请求。

from rest_framework.decorators import action
from rest_framework.response import Response

class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    # 自定义动作,处理GET请求
    @action(detail=True, methods=['get'])
    def recent(self, request, pk=None):
        book = self.get_object()
        # 假设我们有一个方法返回最近出版的书籍(这里仅做示例)
        recent_books = Book.objects.filter(published_date__gte='2023-01-01')
        serializer = self.get_serializer(recent_books, many=True)
        return Response(serializer.data)

    # 另一个自定义动作,处理POST请求
    @action(detail=False, methods=['post'])
    def bulk_create(self, request):
        # 处理批量创建
        serializer = self.get_serializer(data=request.data, many=True)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        return Response(serializer.data, status=201)

@action装饰器参数说明:

  • detail: 布尔值。如果为True,表示这个动作是针对单个对象(即需要pk),如果为False,则针对整个集合。

    • detail=True: 对应URL如 /{prefix}/{lookup}/action_name/

    • detail=False: 对应URL如 /{prefix}/action_name/

  • methods: 列表,指定这个动作响应的HTTP方法,如['get', 'post']。

  • url_path: 自定义URL路径,默认使用函数名。

  • url_name: 为URL命名,用于反向解析。

​参数​

​类型​

​默认值​

​说明​

​必需​

detail

bool

True

指定是详情操作还是集合操作

methods

list

['get']

支持的 HTTP 方法列表

url_path

str

方法名

URL 路径后缀

url_name

str

方法名

路由名称后缀

permission_classes

list

None

专属权限类

authentication_classes

list

None

专属认证类

throttle_classes

list

None

专属限流类

serializer_class

class

None

专属序列化器

pagination_class

class

None

专属分页类

filter_backends

list

None

专属过滤后端

kwargs

dict

{}

额外视图参数

3. 钩子函数

perform_create(), perform_update() 和 perform_destroy() 是三个关键的操作钩子方法,它们提供了在核心操作执行前后添加自定义逻辑的能力。

1. perform_create(serializer)

在创建新对象时,在对象保存到数据库之前或之后执行自定义逻辑。

class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    
    def perform_create(self, serializer):
        # 自动设置作者和创建时间
        serializer.save(
            author=self.request.user,
            created_at=timezone.now()
        )
        
        # 发送通知
        book = serializer.instance
        send_email_notification(
            subject=f"新书创建: {book.title}",
            message=f"书籍 '{book.title}' 已成功创建",
            recipients=['admin@example.com']
        )

在 create() 方法验证数据成功后,实际保存对象到数据库之前。

2. perform_update(serializer)

在更新现有对象时,在对象保存到数据库之前或之后执行自定义逻辑。

class OrderViewSet(viewsets.ModelViewSet):
    queryset = Order.objects.all()
    serializer_class = OrderSerializer
    
    def perform_update(self, serializer):
        # 获取原始对象
        original_order = self.get_object()
        
        # 保存更新
        updated_order = serializer.save(updated_at=timezone.now())
        
        # 记录变更历史
        OrderHistory.objects.create(
            order=updated_order,
            user=self.request.user,
            changes=calculate_changes(original_order, updated_order)
        )
        
        # 状态变更通知
        if original_order.status != updated_order.status:
            send_status_change_notification(updated_order)

在 update() 或 partial_update() 方法验证数据成功后,实际保存更新到数据库之前。

3. perform_destroy(instance)

在删除对象时,在实际从数据库删除之前或之后执行自定义逻辑。

class UserProfileViewSet(viewsets.ModelViewSet):
    queryset = UserProfile.objects.all()
    serializer_class = UserProfileSerializer
    
    def perform_destroy(self, instance):
        # 软删除用户资料
        instance.is_active = False
        instance.deactivated_at = timezone.now()
        instance.deactivated_by = self.request.user
        instance.save()
        
        # 记录删除操作
        DeactivationLog.objects.create(
            user=instance.user,
            deactivated_by=self.request.user,
            reason="用户请求删除"
        )
        
        # 通知用户
        send_deactivation_email(instance.user)

在 destroy() 方法确定对象存在后,实际执行删除操作之前。

4. 分页器

DRF(Django REST Framework)中的分页器(Pagination)用于控制分页行为,即在返回大量数据时,将数据拆分为多个页面。分页可以提升性能并减少单个响应的负载,同时提升用户体验。

DRF提供了三种内置的分页器:

  • ​PageNumberPagination​​:基于页码的分页,如 ?page=2

  • ​LimitOffsetPagination​​:基于偏移的分页,如 ?limit=20&offset=40

  • ​CursorPagination​​:基于游标的分页,提供更安全的分页方式(不暴露页码),适合大型数据集和实时更新的数据流

分页器可以在全局配置

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 10,  # 每页大小
}

也可以在视图中进行设置

from rest_framework.pagination import PageNumberPagination
from rest_framework import viewsets

class LargeResultsSetPagination(PageNumberPagination):
    page_size = 20
    page_size_query_param = 'page_size'
    max_page_size = 100

class MyViewSet(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MySerializer
    pagination_class = LargeResultsSetPagination  # 使用自定义分页

1. PageNumberPagination

使用页码(如page=2),通常需要配合page_size(每页大小)使用。

  • ​参数​​:

    • page_query_param:页码参数名(默认为'page')

    • page_size_query_param:每页大小参数名(默认为None,表示不可由客户端设置)

    • max_page_size:每页最大大小(如果允许客户端设置)

    • page_size:默认每页大小

    • django_paginator_class:使用的Django Paginator类

​自定义示例​​:

class StandardPageNumberPagination(PageNumberPagination):
    page_size = 10  # 默认每页数量
    page_query_param = 'page'  # 页码参数名称
    page_size_query_param = 'page_size'  # 每页数量参数名称
    max_page_size = 50  # 客户端最多允许设置的每页数量
    
# 请求示例
GET /api/books/?page=3&page_size=20

# 响应
{
    "count": 1000,
    "next": "http://api.example.com/books/?page=4",
    "previous": "http://api.example.com/books/?page=2",
    "results": [
        // 当前页数据
    ]
}

2. LimitOffsetPagination

基于数据库的LIMIT和OFFSET。参数为limit(限制数量)和offset(偏移量)。

  • ​参数​​:

    • limit_query_param:每页大小参数名(默认'limit')

    • offset_query_param:偏移量参数名(默认'offset')

    • max_limit:最大每页大小

​自定义示例​​:

class CustomLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 10  # 默认每页数量
    limit_query_param = 'limit'  # 每页数量参数名称
    offset_query_param = 'offset'  # 偏移量参数名称
    max_limit = 100  # 最大允许的每页数量

3. CursorPagination

基于游标的分页,返回一个包含下一页游标的结果。这种分页方式在无序数据中表现更好,并且可以避免页码分页的数据缺失或重复问题(如在分页过程中有新增或删除)。

  • ​参数​​:

    • cursor_query_param:游标参数名(默认'cursor')

    • page_size:每页大小

    • ordering:分页使用的排序字段(通常是创建时间或主键)

    • page_size_query_param:每页大小参数名(可选)

​自定义示例​​:

class CustomCursorPagination(CursorPagination):
    page_size = 10  # 默认每页数量
    cursor_query_param = 'cursor'  # 游标参数名称
    ordering = '-created'  # 按创建时间降序

4. 示例

from rest_framework import generics
from rest_framework.pagination import PageNumberPagination

class MyPaginator(PageNumberPagination):
    page_size = 5
    page_size_query_param = 'page_size'
    max_page_size = 100

class MyListView(generics.ListAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MySerializer
    pagination_class = MyPaginator

分页后的响应结构通常包含:

  • count:总记录数

  • next:下一页的URL(如果没有则为null)

  • previous:上一页的URL(如果没有则为null)

  • results:当前页的数据列表

{
  "count": 100,
  "next": "https://api.example.com/mymodel/?page=2&page_size=5",
  "previous": null,
  "results": [
    // 当前页的数据
  ]
}
  • 分页只用于GET请求,即用于列表接口。

  • 使用分页时,需要权衡性能和用户体验。例如,CursorPagination在大数据集上性能更好,但不提供页码导航。

  • 全局设置的分页器可以被视图级别的设置覆盖。

  • 如果不希望某个视图分页,可以在视图中设置pagination_class = None。

5. 自定义分页响应

可以重写分页器的get_paginated_response方法来自定义响应结构:

class CustomPageNumberPagination(PageNumberPagination):
    def get_paginated_response(self, data):
        return Response({
            'total_pages': self.page.paginator.num_pages,
            'current_page': self.page.number,
            'next_page': self.get_next_link(),
            'prev_page': self.get_previous_link(),
            'data': data
        })

5. 自定义数据集获取

在 Django REST Framework (DRF) 中,get_queryset 和 get_object 是两个核心方法,它们控制着视图如何访问数据。

1. get_queryset 方法详解

get_queryset 决定视图返回的查询集(QuerySet)。默认行为是返回 self.queryset 属性指定的模型查询集:

class BookListView(generics.ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    
    # 默认相当于
    def get_queryset(self):
        return self.queryset.all()

示例:

def get_queryset(self):
    user = self.request.user
    
    # 管理员可以查看所有数据
    if user.is_superuser:
        return super().get_queryset()
    
    # 普通用户只能查看自己的数据
    return super().get_queryset().filter(created_by=user)

2. get_object 方法详解

get_object 用于在详情视图中检索单个对象。默认行为:

class BookDetailView(generics.RetrieveAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    
    # 默认相当于
    def get_object(self):
        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
        
        filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
        obj = get_object_or_404(self.get_queryset(), **filter_kwargs)
        
        self.check_object_permissions(self.request, obj)
        return obj

示例:

class EmployeeDataView(OrganizationModelViewMixin, generics.RetrieveAPIView):
    serializer_class = EmployeeSerializer
    
    def get_queryset(self):
        queryset = super().get_queryset()
        user = self.request.user
        
        # HR可以查看所有员工,经理只能查看自己团队的员工
        if user.role == 'HR':
            return queryset
        elif user.role == 'MANAGER':
            return queryset.filter(team=user.team)
        else:
            return queryset.none()  # 普通员工无访问权限
    
    def get_object(self):
        obj = super().get_object()
        
        # 额外检查:管理员可以查看敏感信息
        if not self.request.user.is_hr and obj.has_sensitive_info:
            # 移除敏感字段
            obj.sensitive_info = None
            
        return obj

最后更新于