当前位置: 首页 > article >正文

Django REST Framework 中 ModelViewSet 的接口方法及参数详解,继承的方法和核心类方法,常用查询方法接口

第一部分(ModelViewSet)

一、ModelViewSet 的继承结构

ModelViewSet 继承自以下类:

ModelViewSet = (
    CreateModelMixin +    # 创建
    RetrieveModelMixin +  # 检索单个
    UpdateModelMixin +    # 更新
    DestroyModelMixin +   # 删除
    ListModelMixin +      # 列表
    GenericViewSet        # 基础视图集
)

二、默认接口方法及参数

以下方法由 ‌mixins‌ 提供,支持 RESTful 标准操作:

方法名HTTP 方法参数说明作用
list(ListModelMixin)GETself, request, *args, **kwargs获取资源列表

create

(CreateModelMixin)

POSTself, request, *args, **kwargs创建新资源

retrieve

(RetrieveModelMixin)

GETself, request, *args, **kwargs (需 pk 或 slug)获取单个资源

update

(UpdateModelMixin)

PUT/PATCHself, request, *args, **kwargs (需 pk 或 slug)全量/部分更新资源

destroy

(DestoryModelMixin)

DELETEself, request, *args, **kwargs (需 pk 或 slug)删除资源
参数统一说明:
  • request‌: Django 请求对象,包含请求数据 (request.data) 和用户信息 (request.user)。
  • *args‌: URL 中捕获的位置参数(如路径参数)。
  • ==‌**‌==kwargs: URL 中捕获的关键字参数(如 pk=1)。

三、核心类方法及参数详解

以下方法由 GenericViewSet 和 GenericAPIView 提供,用于控制视图行为:

方法名参数返回值作用
get_queryset()无参数,但可通过 self.request 访问请求上下文QuerySet返回默认查询集(可覆盖以实现动态过滤)
get_object()无参数,从 URL 参数中提取 pk 或 slug模型实例获取单个对象,支持 lookup_field 自定义查询字段
get_serializer()instance=None, data=None, many=False, partial=False, **kwargs序列化器实例(serializer初始化序列化器,用于请求数据验证和响应数据生成(对需要更新的数据进行验证并返回验证后的数据)
get_serializer_class()无参数,但可通过 self.action 判断当前动作(如 create/update序列化器类动态选择序列化器(例如不同动作使用不同序列化器)
perform_create()serializer (序列化器实例)无,直接保存对象到数据库在创建对象前/后执行额外操作(如设置 created_by=request.user
perform_update()serializer (序列化器实例)无,直接更新对象到数据库在更新对象前/后执行额外操作(如记录日志)
perform_destroy()instance (要删除的模型实例)无,直接删除对象在删除对象前/后执行额外操作(如级联删除关联数据)
filter_queryset()queryset (基础查询集)过滤后的 QuerySet应用所有已配置的过滤器(如 DjangoFilterBackend

四、关键参数扩展说明

1. get_object() 的底层参数
  • lookup_field‌: 默认是 'pk',可通过类属性修改为其他字段(如 slug)。
  • lookup_url_kwarg‌: 默认与 lookup_field 相同,指定从 URL 中提取参数的名称。

示例:

class BookViewSet(ModelViewSet):
    lookup_field = 'isbn'  # 模型字段
    lookup_url_kwarg = 'book_isbn'  # URL 参数名
2. get_serializer() 的参数
  • instance‌: 要更新的模型实例(用于 update 操作)。
  • data‌: 请求数据(request.data)。
  • partial‌: 是否允许部分更新(True 对应 PATCH 请求)。
    • 从请求参数中获取'partial'标识,当值为True时表示PATCH请求(部分更新字段),False时表示PUT请求(完整更新)。通过控制该参数,DRF的序列化器会决定是否进行全字段验证。

五、权限与节流相关方法

方法名参数作用
get_permissions()返回权限类列表(如 [IsAuthenticated]
get_throttles()返回节流类列表(如 [UserRateThrottle]

六、自定义场景示例

1. 动态过滤查询集
def get_queryset(self):
    # 只返回当前用户创建的书籍
    return Book.objects.filter(created_by=self.request.user)
2. 按动作选择序列化器
def get_serializer_class(self):
    if self.action == 'list':
        return BookListSerializer
    return BookDetailSerializer
3. 记录操作日志
def perform_create(self, serializer):
    book = serializer.save(created_by=self.request.user)
    log_action('create', self.request.user, book)

七、完整方法调用流程图

sequenceDiagram
    participant Client
    participant ViewSet
    Client->>ViewSet: HTTP 请求 (如 GET /books/)
    ViewSet->>ViewSet: determine_action()
    ViewSet->>ViewSet: get_queryset()
    ViewSet->>ViewSet: filter_queryset()
    ViewSet->>ViewSet: get_serializer()
    ViewSet->>ViewSet: perform_动作()
    ViewSet->>Client: 返回 Response

 

二部分(查询filter)

一、模型关系假设

# models.py
class PracticeType(models.Model):
    p_type = models.CharField(max_length=50)  # 练习类型字段
    is_active = models.BooleanField(default=True)

class QuestionGroup(models.Model):
    name = models.CharField(max_length=100)
    g_type = models.ForeignKey(PracticeType, on_delete=models.CASCADE)  # 外键关联
    created_at = models.DateTimeField(auto_now_add=True)

class Question(models.Model):
    group = models.ForeignKey(QuestionGroup, on_delete=models.CASCADE, related_name='questions')
    content = models.TextField()
    score = models.IntegerField()

二、查询方法详解(表格)

方法示例代码参数说明作用描述
filter()QuestionGroup.objects.filter(g_type__p_type='数学')g_type__p_type: 跨模型查询 PracticeType.p_type 字段筛选 p_type 为 "数学" 的题组
QuestionGroup.objects.filter(created_at__year=2024)created_at__year: 提取日期字段的年份筛选 2024 年创建的题组
exclude()QuestionGroup.objects.exclude(g_type__is_active=False)g_type__is_active: 排除关联模型中 is_active=False 的题组排除关联到非激活练习类型的题组
order_by()QuestionGroup.objects.order_by('-created_at', 'g_type')-created_at: 按创建时间倒序;g_type: 按外键的默认排序(如 p_type先按创建时间倒序,再按练习类型排序
values()QuestionGroup.objects.values('id', 'g_type__p_type')id: 返回题组 ID;g_type__p_type: 返回关联练习类型的 p_type 字段获取题组 ID 及其关联的练习类型名称
annotate()QuestionGroup.objects.annotate(total_score=Sum('questions__score'))total_score=Sum('questions__score'): 计算每个题组下所有题目的总分为每个题组添加总分注解字段 total_score
QuestionGroup.objects.annotate(avg_score=Avg('questions__score'))avg_score=Avg('questions__score'): 计算每个题组下题目的平均分为每个题组添加平均分注解字段 avg_score

三、参数详细说明

1. ==‌filter(**‌==kwargs) - 过滤
  • 参数语法‌: 字段__操作符=值(如 created_at__year=2024
  • 跨模型查询‌: 使用双下划线 __ 跳转关联模型字段(如 g_type__p_type)。
  • 示例‌:
    
    # 查询 p_type 为 "物理" 的题组
    groups = QuestionGroup.objects.filter(g_type__p_type='物理')
    
    # 查询 2023 年之后创建的题组
    groups = QuestionGroup.objects.filter(created_at__year__gte=2023)
2. ==‌exclude(**‌==kwargs) - 排除
  • 参数语法‌: 同 filter(),但排除满足条件的对象。
  • 示例‌:
    
    # 排除关联到非激活练习类型的题组
    groups = QuestionGroup.objects.exclude(g_type__is_active=False)
    
    # 排除 p_type 为 "化学" 的题组
    groups = QuestionGroup.objects.exclude(g_type__p_type='化学')
3. ‌order_by(*fields)‌ - 排序
  • 参数语法‌: 字段名前加 - 表示倒序(如 -created_at)。
  • 跨模型排序‌: 支持按关联模型字段排序(如 g_type__p_type)。
  • 示例‌:
    
    # 按练习类型名称升序,再按创建时间倒序
    groups = QuestionGroup.objects.order_by('g_type__p_type', '-created_at')
4. ‌values(*fields)‌ - 取字段
  • 参数语法‌: 指定要返回的字段或关联字段(如 g_type__p_type)。
  • 返回结果‌: 字典列表(而非模型对象)。
  • 示例‌:
    
    # 获取所有题组的 ID、名称及其关联的练习类型名称
    data = QuestionGroup.objects.values('id', 'name', 'g_type__p_type')
5. ‌annotate(别名=聚合函数)‌ - 注解
  • 参数语法‌: 使用聚合函数(如 CountSumAvg)生成计算字段。
  • 跨模型聚合‌: 通过关联模型的 related_name(如 questions)访问子对象。
  • 示例‌:
    
    from django.db.models import Count, Sum, Avg
    
    # 统计每个题组的问题数量
    groups = QuestionGroup.objects.annotate(question_count=Count('questions'))
    
    # 计算每个题组的总分和平均分
    groups = QuestionGroup.objects.annotate(
        total_score=Sum('questions__score'),
        avg_score=Avg('questions__score')
    )

四、高级用法

1. 链式调用
# 查询 2024 年创建的数学题组,按总分降序排列
groups = QuestionGroup.objects.filter(
    g_type__p_type='数学',
    created_at__year=2024
).annotate(
    total_score=Sum('questions__score')
).order_by('-total_score')
2. 跨多级模型查询
# 查询所有题目分数大于 80 的题组
groups = QuestionGroup.objects.filter(questions__score__gt=80)
3. 空值处理
# 查询没有关联任何问题的题组
groups = QuestionGroup.objects.filter(questions__isnull=True)

五、性能优化

  • select_related‌: 用于外键或一对一字段的预加载(减少查询次数)。
    
    # 预加载 g_type 关联的 PracticeType 对象
    groups = QuestionGroup.objects.select_related('g_type').filter(g_type__p_type='数学')
  • prefetch_related‌: 用于多对多或一对多字段的预加载。
    # 预加载题组下的所有问题
    groups = QuestionGroup.objects.prefetch_related('questions').annotate(total_score=Sum('questions__score'))

 


http://www.kler.cn/a/583012.html

相关文章:

  • 多模态推理模型相关开源工作
  • STM32使用EXTI触发进行软件消抖(更新中)
  • C# AOT生成的hellowwordEXE运行占用多少内存1-5MB?
  • ESP8266远端可变的UDP传输
  • Java高频面试之集合-09
  • IDEA修改项目的JDK版本(无缝切换8和11)
  • 前端发布缓存导致白屏解决方案
  • SpringBoot实现文件上传
  • Excel两列和依次相减
  • 【C++入门】变量和基本类型
  • 版本控制器Git(2)
  • [数据结构]排序之希尔排序( 缩小增量排序 )
  • upload-labs-master通关攻略(13~16)
  • 计算机视觉|一文读懂NeRF:为3D场景重建带来新突破
  • CMD批处理一些冷门命令,编写windows脚本常用?
  • java每日精进 3.11 【多租户】
  • ST电机库电流采样 三电阻单ADC
  • Oracle VirtualBox安装CentOS 7
  • FFmpeg入门:最简单的音视频播放器(Plus优化版)
  • dns劫持是什么?常见的劫持类型有哪些?如何预防?