00:00

文章目录

加载目录中...

DRF的Request对象

1. 核心属性详解

DRF 的 Request 对象最重要的几个属性是:.data, .query_params, .user, .auth

a. request.data - 解析后的请求体

这是 最常用 的属性,它返回解析后的请求正文内容。

  • 自动解析:DRF 会根据请求的 Content-Type 头(如 application/json, application/x-www-form-urlencoded, multipart/form-data)自动调用相应的解析器 (Parser) 来处理 request.body,你无需手动处理原始字节数据。
  • 支持所有方法:无论请求方法是 POST, PUT, 还是 PATCH,解析后的数据都统一放在 request.data 中。
  • 数据类型:通常是一个 QueryDict 或普通的字典(对于 JSON),处理方式与 Python 字典一致。

使用示例:

from rest_framework.views import APIView
from rest_framework.response import Response

class ArticleView(APIView):
    def post(self, request):
        # 假设客户端发送 JSON: {"title": "My Article", "content": "Hello World", "published": true}
        title = request.data.get('title')
        content = request.data.get('content')
        is_published = request.data.get('published', False) # 提供默认值

        # 创建文章逻辑 ...
        # article = Article.objects.create(title=title, ...)

        return Response({'id': article.id, 'title': title}, status=201)

    def put(self, request, pk):
        # 更新文章,request.data 包含要更新的字段
        # 局部更新也可以用 patch 方法
        article = Article.objects.get(pk=pk)
        # ... 更新逻辑
        return Response({'message': 'Updated'})

b. request.query_params - 查询参数

此属性用于获取 URL 中的查询字符串参数(即 ?key=value&key2=value2 部分)。

  • 等同于 Django 的 request.GET:但命名为 query_params 更准确,因为它不仅用于 GET 请求,其他请求方法也可以带有查询参数。
  • 数据类型:这是一个 QueryDict 对象,可以像字典一样使用。

使用示例:

class ArticleListView(APIView):
    def get(self, request):
        # 处理 /api/articles/?page=2&search=drf&sort=-created_at
        page_number = request.query_params.get('page', 1) # 获取 'page' 参数,默认为 1
        search_query = request.query_params.get('search', '')
        sort_order = request.query_params.get('sort', 'id')

        # 使用这些参数进行过滤、分页和排序
        articles = Article.objects.all()
        if search_query:
            articles = articles.filter(title__icontains=search_query)
        articles = articles.order_by(sort_order)

        # ... 序列化和分页逻辑
        serializer = ArticleSerializer(articles, many=True)
        return Response(serializer.data)

c. request.userrequest.auth - 认证信息

这两个属性由 DRF 的认证系统自动填充。

  • request.user: 返回当前请求的用户对象。
    • 如果用户已认证,它是一个 User 模型实例(或自定义用户模型)。
    • 如果用户未认证,它是 AnonymousUser 的一个实例。
    • 你通常不需要手动检查 if request.user.is_authenticated:,而是通过配置权限类 (Permissions)(如 IsAuthenticated)来让 DRF 在调用视图之前自动处理未认证的情况。
  • request.auth: 用于存储额外的认证信息。
    • 在使用 TokenAuthentication 时,request.authToken 模型实例。
    • 在使用 JWT 时,request.auth 是解码后的 token 内容(通常是一个字典)。
    • 在其他认证方案中,它可能是 None

使用示例:

from rest_framework.permissions import IsAuthenticated

class UserProfileView(APIView):
    # 设置权限类,确保只有认证用户才能访问
    permission_classes = [IsAuthenticated]

    def get(self, request):
        # 因为通过了权限检查,这里的 request.user 一定是认证用户
        user = request.user
        profile = user.profile
        # ... 获取用户配置信息
        return Response({'username': user.username, 'email': user.email})

    def post(self, request):
        # 可以使用 request.user 来关联创建对象
        serializer = ArticleSerializer(data=request.data)
        if serializer.is_valid():
            # 将当前用户作为作者存入
            serializer.save(author=request.user)
            return Response(serializer.data, status=201)
        return Response(serializer.errors, status=400)

2. 其他有用属性和方法

  • request.method: 获取 HTTP 请求方法(如 'POST', 'GET')。注意:这实际上是底层 Django HttpRequest 的属性,DRF 的 Request 对象通过代理暴露它。
  • request.content_type: 获取请求体的媒体类型(如 'application/json')。
  • request.stream: 如果需要以流的形式处理请求体,可以访问此属性,但绝大多数情况下用不到,因为 request.data 已经处理好了。

3. 在序列化器中使用 request

在视图里,你可以将 request 中的信息(如当前用户)通过上下文 (context) 传递给序列化器。

class MyView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        # 将 request 放入序列化器的上下文中
        serializer = MyModelSerializer(
            data=request.data,
            context={'request': request} # 关键在这里!
        )
        if serializer.is_valid():
            # 在序列化器的 create 或 update 方法中就可以通过 self.context['request'] 访问到 request 和 request.user
            serializer.save()
            return Response(serializer.data, status=201)
        return Response(serializer.errors, status=400)

然后在序列化器中,你就可以使用这个上下文了:

class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = '__all__'

    def create(self, validated_data):
        # 从上下文中获取当前用户
        request = self.context.get('request')
        if request and hasattr(request, 'user'):
            # 在创建对象时自动设置 owner 字段为当前用户
            validated_data['owner'] = request.user
        return super().create(validated_data)

4. 在哪种视图中可以使用?

DRF 的 Request 对象会在所有基于 DRF 的视图类中被自动创建和传递。这包括:

  • APIView 的子类
  • 所有通用视图(GenericAPIView, ListCreateAPIView, ...)
  • 视图集(ViewSet, ModelViewSet, ...)

总结一下 DRF request 的使用要点:

  1. 读数据:用 request.data(请求体),用 request.query_params(URL参数)。
  2. 用户认证:用 request.user,并配合权限类来保护视图,而不是在视图逻辑里手动检查。
  3. 传递上下文:需要在新创建的对象中关联当前用户或其他请求信息时,通过 contextrequest 传递给序列化器,然后在序列化器的 .create().update() 方法中使用。
  4. 无需手动解析:永远不要再写 json.loads(request.body) 这样的代码,DRF 已经为你做好了。
返回文章列表

评论区 0