DRF 请求对象 #

一、Request对象概述 #

1.1 什么是Request #

DRF的Request对象扩展了Django的HttpRequest,提供了更方便的API数据处理功能。

text
Request继承关系
┌─────────────────────────────────────┐
│        Django HttpRequest           │
│  - GET, POST, META等属性            │
│  - 原始请求数据                     │
└─────────────────────────────────────┘
                  │
                  ▼
┌─────────────────────────────────────┐
│           DRF Request               │
│  - data: 解析后的请求体             │
│  - query_params: 查询参数           │
│  - user: 认证用户                   │
│  - auth: 认证信息                   │
└─────────────────────────────────────┘

1.2 核心属性 #

属性 说明
data 解析后的请求体数据
query_params 查询参数
user 认证用户
auth 认证信息
method HTTP方法
content_type 内容类型
stream 原始请求流

二、request.data #

2.1 基本用法 #

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

class ArticleView(APIView):
    def post(self, request):
        title = request.data.get('title')
        content = request.data.get('content')
        
        return Response({
            'title': title,
            'content': content
        })

2.2 数据类型 #

python
class DataView(APIView):
    def post(self, request):
        print(type(request.data))
        
        if isinstance(request.data, dict):
            for key, value in request.data.items():
                print(f'{key}: {value}')
        
        return Response({'received': True})

2.3 与POST的区别 #

python
class CompareView(APIView):
    def post(self, request):
        return Response({
            'data': request.data,
            'POST': request.POST,
            'data_keys': list(request.data.keys()),
            'POST_keys': list(request.POST.keys())
        })
特性 request.data request.POST
支持格式 JSON, Form, MultiPart 仅Form数据
解析方式 自动解析 Django原生
返回类型 dict QueryDict

三、query_params #

3.1 基本用法 #

python
class SearchView(APIView):
    def get(self, request):
        keyword = request.query_params.get('keyword', '')
        page = request.query_params.get('page', 1)
        page_size = request.query_params.get('page_size', 10)
        
        return Response({
            'keyword': keyword,
            'page': page,
            'page_size': page_size
        })

3.2 获取多个值 #

python
class FilterView(APIView):
    def get(self, request):
        categories = request.query_params.getlist('category')
        tags = request.query_params.getlist('tag')
        
        return Response({
            'categories': categories,
            'tags': tags
        })

3.3 类型转换 #

python
class TypedParamsView(APIView):
    def get(self, request):
        try:
            page = int(request.query_params.get('page', 1))
            page_size = int(request.query_params.get('page_size', 10))
            is_active = request.query_params.get('is_active', 'true').lower() == 'true'
        except ValueError:
            return Response({'error': '参数类型错误'}, status=400)
        
        return Response({
            'page': page,
            'page_size': page_size,
            'is_active': is_active
        })

四、请求头 #

4.1 获取请求头 #

python
class HeadersView(APIView):
    def get(self, request):
        content_type = request.META.get('CONTENT_TYPE')
        authorization = request.META.get('HTTP_AUTHORIZATION')
        user_agent = request.META.get('HTTP_USER_AGENT')
        
        return Response({
            'content_type': content_type,
            'authorization': authorization,
            'user_agent': user_agent
        })

4.2 request.headers #

python
class HeadersView(APIView):
    def get(self, request):
        headers = request.headers
        
        return Response({
            'content_type': headers.get('Content-Type'),
            'authorization': headers.get('Authorization'),
            'user_agent': headers.get('User-Agent'),
            'all_headers': dict(headers)
        })

五、文件上传 #

5.1 单文件上传 #

python
class FileUploadView(APIView):
    def post(self, request):
        file = request.FILES.get('file')
        
        if not file:
            return Response({'error': '请选择文件'}, status=400)
        
        file_info = {
            'name': file.name,
            'size': file.size,
            'content_type': file.content_type,
        }
        
        return Response(file_info)

5.2 多文件上传 #

python
class MultiFileUploadView(APIView):
    def post(self, request):
        files = request.FILES.getlist('files')
        
        files_info = []
        for file in files:
            files_info.append({
                'name': file.name,
                'size': file.size,
                'content_type': file.content_type,
            })
        
        return Response({'files': files_info})

5.3 保存文件 #

python
import os
from django.conf import settings

class FileUploadView(APIView):
    def post(self, request):
        file = request.FILES.get('file')
        
        if not file:
            return Response({'error': '请选择文件'}, status=400)
        
        upload_dir = os.path.join(settings.MEDIA_ROOT, 'uploads')
        os.makedirs(upload_dir, exist_ok=True)
        
        file_path = os.path.join(upload_dir, file.name)
        
        with open(file_path, 'wb+') as destination:
            for chunk in file.chunks():
                destination.write(chunk)
        
        return Response({
            'message': '上传成功',
            'file_name': file.name,
            'file_path': file_path
        })

六、用户信息 #

6.1 获取用户 #

python
class UserView(APIView):
    def get(self, request):
        if request.user.is_authenticated:
            return Response({
                'user_id': request.user.id,
                'username': request.user.username,
                'email': request.user.email,
                'is_staff': request.user.is_staff,
            })
        return Response({'user': 'anonymous'})

6.2 认证信息 #

python
class AuthView(APIView):
    def get(self, request):
        return Response({
            'user': str(request.user),
            'auth': str(request.auth),
            'is_authenticated': request.user.is_authenticated,
        })

七、请求方法 #

7.1 判断请求方法 #

python
class MethodView(APIView):
    def get(self, request):
        return Response({'method': request.method})
    
    def post(self, request):
        return Response({'method': request.method})
    
    def put(self, request):
        return Response({'method': request.method})
    
    def patch(self, request):
        return Response({'method': request.method})
    
    def delete(self, request):
        return Response({'method': request.method})

7.2 条件处理 #

python
class ConditionalView(APIView):
    def get(self, request):
        if request.method == 'GET':
            return self.handle_get(request)
        elif request.method == 'POST':
            return self.handle_post(request)
        
    def handle_get(self, request):
        return Response({'action': 'get'})
    
    def handle_post(self, request):
        return Response({'action': 'post'})

八、内容协商 #

8.1 获取内容类型 #

python
class ContentView(APIView):
    def post(self, request):
        return Response({
            'content_type': request.content_type,
            'accepted_type': request.accepted_media_type,
            'accepted_renderer': str(request.accepted_renderer),
        })

8.2 原始请求流 #

python
class RawView(APIView):
    def post(self, request):
        raw_data = request.stream.read()
        
        return Response({
            'raw_data': raw_data.decode('utf-8'),
            'content_type': request.content_type,
        })

九、实用方法 #

9.1 获取客户端IP #

python
def get_client_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip

class IPView(APIView):
    def get(self, request):
        return Response({'ip': get_client_ip(request)})

9.2 获取User-Agent #

python
class UserAgentView(APIView):
    def get(self, request):
        user_agent = request.META.get('HTTP_USER_AGENT', '')
        
        is_mobile = 'Mobile' in user_agent
        is_ios = 'iPhone' in user_agent or 'iPad' in user_agent
        is_android = 'Android' in user_agent
        
        return Response({
            'user_agent': user_agent,
            'is_mobile': is_mobile,
            'is_ios': is_ios,
            'is_android': is_android,
        })

9.3 请求日志 #

python
import logging

logger = logging.getLogger(__name__)

class LoggingView(APIView):
    def post(self, request):
        logger.info(f'Request from {get_client_ip(request)}')
        logger.info(f'User: {request.user}')
        logger.info(f'Method: {request.method}')
        logger.info(f'Path: {request.path}')
        logger.info(f'Data: {request.data}')
        
        return Response({'logged': True})

十、总结 #

本章学习了DRF Request对象:

  • request.data:解析后的请求体数据
  • query_params:查询参数处理
  • 请求头:获取HTTP头信息
  • 文件上传:处理文件上传
  • 用户信息:获取认证用户

让我们继续学习Response对象!

最后更新:2026-03-28