DRF 函数视图 #
一、函数视图概述 #
1.1 什么是函数视图 #
函数视图是DRF中最基础的视图形式,使用Python函数处理HTTP请求,通过装饰器声明支持的HTTP方法。
text
函数视图特点
├── 简单直观:类似Django传统视图
├── 灵活控制:完全控制请求处理流程
├── 适合简单API:快速实现简单接口
└── 代码集中:所有逻辑在一个函数中
1.2 基本语法 #
python
from rest_framework.decorators import api_view
from rest_framework.response import Response
@api_view(['GET'])
def hello_world(request):
return Response({'message': 'Hello, World!'})
二、@api_view装饰器 #
2.1 基本用法 #
python
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
@api_view(['GET', 'POST'])
def article_list(request):
if request.method == 'GET':
articles = Article.objects.all()
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
2.2 支持的HTTP方法 #
python
@api_view(['GET']) # 只支持GET
@api_view(['POST']) # 只支持POST
@api_view(['GET', 'POST']) # 支持GET和POST
@api_view(['PUT', 'PATCH']) # 支持PUT和PATCH
@api_view(['DELETE']) # 只支持DELETE
@api_view(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']) # 支持所有方法
2.3 HTTP方法映射 #
| HTTP方法 | 用途 | 状态码 |
|---|---|---|
| GET | 获取资源 | 200 OK |
| POST | 创建资源 | 201 Created |
| PUT | 完整更新资源 | 200 OK |
| PATCH | 部分更新资源 | 200 OK |
| DELETE | 删除资源 | 204 No Content |
三、请求处理 #
3.1 Request对象 #
DRF扩展了Django的HttpRequest,提供了更多功能:
python
@api_view(['GET', 'POST'])
def example_view(request):
print(request.method) # HTTP方法
print(request.data) # 解析后的请求体
print(request.query_params) # 查询参数
print(request.user) # 当前用户
print(request.auth) # 认证信息
print(request.headers) # 请求头
return Response({'status': 'ok'})
3.2 获取请求参数 #
python
@api_view(['GET'])
def article_detail(request, pk):
article = get_object_or_404(Article, pk=pk)
serializer = ArticleSerializer(article)
return Response(serializer.data)
@api_view(['GET'])
def article_search(request):
keyword = request.query_params.get('keyword', '')
category = request.query_params.get('category')
articles = Article.objects.all()
if keyword:
articles = articles.filter(title__icontains=keyword)
if category:
articles = articles.filter(category_id=category)
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
3.3 获取请求体数据 #
python
@api_view(['POST'])
def create_article(request):
title = request.data.get('title')
content = request.data.get('content')
author = request.data.get('author')
if not title:
return Response(
{'error': '标题不能为空'},
status=status.HTTP_400_BAD_REQUEST
)
article = Article.objects.create(
title=title,
content=content,
author=author
)
serializer = ArticleSerializer(article)
return Response(serializer.data, status=status.HTTP_201_CREATED)
四、Response对象 #
4.1 基本响应 #
python
from rest_framework.response import Response
@api_view(['GET'])
def simple_response(request):
return Response({'message': '成功'})
@api_view(['GET'])
def response_with_status(request):
return Response(
{'message': '创建成功'},
status=status.HTTP_201_CREATED
)
@api_view(['GET'])
def response_with_headers(request):
return Response(
{'message': '成功'},
headers={'X-Custom-Header': 'value'}
)
4.2 常用状态码 #
python
from rest_framework import status
@api_view(['GET'])
def get_data(request):
return Response(data, status=status.HTTP_200_OK)
@api_view(['POST'])
def create_data(request):
return Response(data, status=status.HTTP_201_CREATED)
@api_view(['GET'])
def not_found(request):
return Response(
{'error': '资源不存在'},
status=status.HTTP_404_NOT_FOUND
)
@api_view(['POST'])
def bad_request(request):
return Response(
{'error': '参数错误'},
status=status.HTTP_400_BAD_REQUEST
)
@api_view(['DELETE'])
def delete_data(request, pk):
return Response(status=status.HTTP_204_NO_CONTENT)
4.3 状态码常量 #
| 常量 | 值 | 说明 |
|---|---|---|
| HTTP_200_OK | 200 | 成功 |
| HTTP_201_CREATED | 201 | 创建成功 |
| HTTP_204_NO_CONTENT | 204 | 无内容 |
| HTTP_400_BAD_REQUEST | 400 | 请求错误 |
| HTTP_401_UNAUTHORIZED | 401 | 未认证 |
| HTTP_403_FORBIDDEN | 403 | 禁止访问 |
| HTTP_404_NOT_FOUND | 404 | 未找到 |
| HTTP_500_INTERNAL_SERVER_ERROR | 500 | 服务器错误 |
五、完整CRUD示例 #
5.1 列表和创建 #
python
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from django.shortcuts import get_object_or_404
from .models import Article
from .serializers import ArticleSerializer
@api_view(['GET', 'POST'])
def article_list(request):
if request.method == 'GET':
articles = Article.objects.all()
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
5.2 详情、更新和删除 #
python
@api_view(['GET', 'PUT', 'PATCH', 'DELETE'])
def article_detail(request, pk):
article = get_object_or_404(Article, pk=pk)
if request.method == 'GET':
serializer = ArticleSerializer(article)
return Response(serializer.data)
elif request.method == 'PUT':
serializer = ArticleSerializer(article, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'PATCH':
serializer = ArticleSerializer(article, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
article.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
六、URL配置 #
6.1 配置路由 #
python
from django.urls import path
from . import views
urlpatterns = [
path('articles/', views.article_list, name='article-list'),
path('articles/<int:pk>/', views.article_detail, name='article-detail'),
]
6.2 带参数的路由 #
python
urlpatterns = [
path('articles/', views.article_list, name='article-list'),
path('articles/<int:pk>/', views.article_detail, name='article-detail'),
path('categories/<int:category_id>/articles/', views.category_articles, name='category-articles'),
path('users/<str:username>/articles/', views.user_articles, name='user-articles'),
]
6.3 视图函数 #
python
@api_view(['GET'])
def category_articles(request, category_id):
articles = Article.objects.filter(category_id=category_id)
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
@api_view(['GET'])
def user_articles(request, username):
articles = Article.objects.filter(author__username=username)
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
七、装饰器组合 #
7.1 authentication_classes #
python
from rest_framework.decorators import api_view, authentication_classes
from rest_framework.authentication import TokenAuthentication, SessionAuthentication
@api_view(['GET'])
@authentication_classes([TokenAuthentication, SessionAuthentication])
def protected_view(request):
return Response({'message': '认证成功'})
7.2 permission_classes #
python
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated, IsAdminUser
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def user_profile(request):
serializer = UserSerializer(request.user)
return Response(serializer.data)
@api_view(['GET'])
@permission_classes([IsAdminUser])
def admin_only(request):
return Response({'message': '管理员专属'})
7.3 throttle_classes #
python
from rest_framework.decorators import api_view, throttle_classes
from rest_framework.throttling import AnonRateThrottle, UserRateThrottle
class OncePerDayThrottle(AnonRateThrottle):
rate = '1/day'
@api_view(['GET'])
@throttle_classes([OncePerDayThrottle])
def limited_access(request):
return Response({'message': '每天只能访问一次'})
7.4 schema装饰器 #
python
from rest_framework.decorators import api_view, schema
from rest_framework.schemas import AutoSchema
class CustomSchema(AutoSchema):
def get_description(self, path, method):
return '自定义API描述'
@api_view(['GET'])
@schema(CustomSchema())
def custom_schema_view(request):
return Response({'message': 'ok'})
7.5 组合使用 #
python
from rest_framework.decorators import (
api_view, authentication_classes, permission_classes, throttle_classes
)
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.throttling import UserRateThrottle
@api_view(['GET', 'POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
@throttle_classes([UserRateThrottle])
def protected_article_list(request):
if request.method == 'GET':
articles = Article.objects.all()
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid():
serializer.save(author=request.user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
八、错误处理 #
8.1 基本错误处理 #
python
from django.core.exceptions import ObjectDoesNotExist
@api_view(['GET'])
def article_detail(request, pk):
try:
article = Article.objects.get(pk=pk)
serializer = ArticleSerializer(article)
return Response(serializer.data)
except ObjectDoesNotExist:
return Response(
{'error': '文章不存在'},
status=status.HTTP_404_NOT_FOUND
)
8.2 使用get_object_or_404 #
python
from django.shortcuts import get_object_or_404
@api_view(['GET'])
def article_detail(request, pk):
article = get_object_or_404(Article, pk=pk)
serializer = ArticleSerializer(article)
return Response(serializer.data)
8.3 自定义异常处理 #
python
from rest_framework.exceptions import APIException
class ArticleNotFound(APIException):
status_code = 404
default_detail = '文章不存在'
default_code = 'article_not_found'
@api_view(['GET'])
def article_detail(request, pk):
try:
article = Article.objects.get(pk=pk)
except Article.DoesNotExist:
raise ArticleNotFound()
serializer = ArticleSerializer(article)
return Response(serializer.data)
8.4 验证错误 #
python
from rest_framework.exceptions import ValidationError
@api_view(['POST'])
def create_article(request):
if not request.data.get('title'):
raise ValidationError({'title': '标题不能为空'})
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
九、实用示例 #
9.1 搜索API #
python
@api_view(['GET'])
def article_search(request):
keyword = request.query_params.get('keyword', '')
category = request.query_params.get('category')
page = int(request.query_params.get('page', 1))
page_size = int(request.query_params.get('page_size', 10))
articles = Article.objects.all()
if keyword:
articles = articles.filter(
models.Q(title__icontains=keyword) |
models.Q(content__icontains=keyword)
)
if category:
articles = articles.filter(category_id=category)
total = articles.count()
start = (page - 1) * page_size
end = start + page_size
articles = articles[start:end]
serializer = ArticleSerializer(articles, many=True)
return Response({
'total': total,
'page': page,
'page_size': page_size,
'results': serializer.data
})
9.2 批量操作 #
python
@api_view(['POST'])
def batch_delete(request):
ids = request.data.get('ids', [])
if not ids:
return Response(
{'error': '请提供要删除的ID列表'},
status=status.HTTP_400_BAD_REQUEST
)
deleted, _ = Article.objects.filter(id__in=ids).delete()
return Response({
'message': f'成功删除{deleted}条记录'
})
9.3 文件上传 #
python
@api_view(['POST'])
def upload_file(request):
file = request.FILES.get('file')
if not file:
return Response(
{'error': '请选择文件'},
status=status.HTTP_400_BAD_REQUEST
)
import os
from django.conf import settings
file_path = os.path.join(settings.MEDIA_ROOT, 'uploads', 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_size': file.size
})
十、函数视图最佳实践 #
10.1 代码组织 #
python
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from django.shortcuts import get_object_or_404
from .models import Article
from .serializers import ArticleSerializer
@api_view(['GET', 'POST'])
def article_list(request):
if request.method == 'GET':
return _list_articles(request)
return _create_article(request)
def _list_articles(request):
articles = Article.objects.all()
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
def _create_article(request):
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
10.2 使用序列化器验证 #
python
@api_view(['POST'])
def create_article(request):
serializer = ArticleSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
10.3 统一响应格式 #
python
def success_response(data, message='操作成功', status_code=status.HTTP_200_OK):
return Response({
'success': True,
'message': message,
'data': data
}, status=status_code)
def error_response(message, errors=None, status_code=status.HTTP_400_BAD_REQUEST):
response_data = {
'success': False,
'message': message
}
if errors:
response_data['errors'] = errors
return Response(response_data, status=status_code)
@api_view(['GET'])
def article_list(request):
articles = Article.objects.all()
serializer = ArticleSerializer(articles, many=True)
return success_response(serializer.data)
@api_view(['POST'])
def create_article(request):
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return success_response(serializer.data, '创建成功', status.HTTP_201_CREATED)
return error_response('验证失败', serializer.errors)
十一、总结 #
本章学习了DRF函数视图:
- @api_view装饰器:声明支持的HTTP方法
- Request对象:处理请求数据
- Response对象:构建响应
- 装饰器组合:认证、权限、限流
- 错误处理:异常处理和验证
函数视图适合简单的API场景,让我们继续学习类视图!
最后更新:2026-03-28