
Django REST Framework实战从零构建企业级API服务【免费下载链接】Python-100-DaysPython - 100天从新手到大师项目地址: https://gitcode.com/GitHub_Trending/py/Python-100-Days在当今前后端分离的开发模式中API已成为连接客户端与服务端的核心桥梁。然而许多开发者在构建API时常常陷入困惑如何设计既规范又高效的接口如何确保API的安全性如何处理复杂的业务逻辑本文将带你从实际问题出发通过Django REST FrameworkDRF构建一套完整的RESTful API解决方案。为什么选择DRF解决传统开发痛点在传统Web开发中前后端耦合严重每次需求变更都需要双方协调修改。RESTful架构的出现让前后端能够独立开发、独立部署。DRF作为Django生态中最成熟的API框架提供了以下核心优势开箱即用的API视图基于类的视图系统让CRUD操作变得异常简单强大的序列化器自动处理数据验证和转换支持复杂嵌套关系丰富的认证授权机制从基础认证到JWT满足不同安全需求可扩展的过滤和分页轻松处理大数据集的查询和展示自动生成的API文档减少文档编写和维护成本项目实战构建图书管理系统API让我们通过一个实际的图书管理系统案例逐步掌握DRF的核心技术。假设我们需要为图书馆开发一套API支持图书的增删改查、借阅记录管理等功能。第一步环境搭建与基础配置首先创建Django项目并安装DRF# 创建项目目录 mkdir library_api cd library_api # 创建虚拟环境 python -m venv venv source venv/bin/activate # Linux/Mac # 或 venv\Scripts\activate # Windows # 安装依赖 pip install django djangorestframework django-filter # 创建Django项目 django-admin startproject library . django-admin startapp books配置settings.py中的DRF# settings.py INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, rest_framework, books, ] REST_FRAMEWORK { DEFAULT_PERMISSION_CLASSES: [ rest_framework.permissions.IsAuthenticatedOrReadOnly, ], DEFAULT_AUTHENTICATION_CLASSES: [ rest_framework.authentication.SessionAuthentication, rest_framework.authentication.BasicAuthentication, ], DEFAULT_PAGINATION_CLASS: rest_framework.pagination.PageNumberPagination, PAGE_SIZE: 20 }第二步设计数据模型良好的数据库设计是API稳定性的基础。我们创建图书和借阅记录两个主要模型# books/models.py from django.db import models from django.contrib.auth.models import User class Book(models.Model): 图书模型 CATEGORY_CHOICES [ (fiction, 小说), (science, 科技), (history, 历史), (education, 教育), (other, 其他), ] isbn models.CharField(ISBN号, max_length13, uniqueTrue) title models.CharField(书名, max_length200) author models.CharField(作者, max_length100) publisher models.CharField(出版社, max_length100) publish_date models.DateField(出版日期) category models.CharField(分类, max_length20, choicesCATEGORY_CHOICES) price models.DecimalField(价格, max_digits8, decimal_places2) stock models.IntegerField(库存数量, default1) available models.BooleanField(可借阅, defaultTrue) created_at models.DateTimeField(创建时间, auto_now_addTrue) updated_at models.DateTimeField(更新时间, auto_nowTrue) class Meta: ordering [-created_at] verbose_name 图书 verbose_name_plural 图书 def __str__(self): return f{self.title} - {self.author} class BorrowRecord(models.Model): 借阅记录模型 STATUS_CHOICES [ (borrowed, 借阅中), (returned, 已归还), (overdue, 已逾期), ] book models.ForeignKey(Book, on_deletemodels.CASCADE, related_nameborrow_records) user models.ForeignKey(User, on_deletemodels.CASCADE, related_nameborrow_records) borrow_date models.DateField(借阅日期, auto_now_addTrue) due_date models.DateField(应还日期) return_date models.DateField(归还日期, nullTrue, blankTrue) status models.CharField(状态, max_length20, choicesSTATUS_CHOICES, defaultborrowed) created_at models.DateTimeField(创建时间, auto_now_addTrue) class Meta: ordering [-borrow_date] verbose_name 借阅记录 verbose_name_plural 借阅记录 def __str__(self): return f{self.user.username}借阅《{self.book.title}》第三步创建序列化器序列化器是DRF的核心组件负责数据验证和转换。我们为图书模型创建两个序列化器一个用于列表展示一个用于详细展示# books/serializers.py from rest_framework import serializers from .models import Book, BorrowRecord from django.contrib.auth.models import User class BookListSerializer(serializers.ModelSerializer): 图书列表序列化器 category_display serializers.CharField(sourceget_category_display, read_onlyTrue) class Meta: model Book fields [id, isbn, title, author, category, category_display, price, available, stock] def validate_isbn(self, value): 验证ISBN号格式 if len(value) not in [10, 13]: raise serializers.ValidationError(ISBN号必须是10位或13位) return value def validate_stock(self, value): 验证库存数量 if value 0: raise serializers.ValidationError(库存数量不能为负数) return value class BookDetailSerializer(serializers.ModelSerializer): 图书详情序列化器 category_display serializers.CharField(sourceget_category_display, read_onlyTrue) borrow_count serializers.SerializerMethodField() class Meta: model Book fields __all__ def get_borrow_count(self, obj): 获取借阅次数 return obj.borrow_records.count() class UserSerializer(serializers.ModelSerializer): 用户序列化器 class Meta: model User fields [id, username, email, first_name, last_name] class BorrowRecordSerializer(serializers.ModelSerializer): 借阅记录序列化器 book_title serializers.CharField(sourcebook.title, read_onlyTrue) user_name serializers.CharField(sourceuser.username, read_onlyTrue) class Meta: model BorrowRecord fields [id, book, book_title, user, user_name, borrow_date, due_date, return_date, status] read_only_fields [borrow_date, status] def validate(self, data): 验证借阅逻辑 book data.get(book) user data.get(user) # 检查图书是否可借 if not book.available: raise serializers.ValidationError(该图书暂不可借) # 检查用户是否已借阅该图书 if BorrowRecord.objects.filter(bookbook, useruser, statusborrowed).exists(): raise serializers.ValidationError(您已经借阅了该图书) # 检查用户借阅数量限制假设最多借5本 borrowed_count BorrowRecord.objects.filter(useruser, statusborrowed).count() if borrowed_count 5: raise serializers.ValidationError(您已达到最大借阅数量) return data第四步实现视图和路由DRF提供了多种视图实现方式我们选择最灵活的视图集ViewSet# books/views.py from rest_framework import viewsets, filters, status from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated, IsAdminUser from django_filters.rest_framework import DjangoFilterBackend from .models import Book, BorrowRecord from .serializers import BookListSerializer, BookDetailSerializer, BorrowRecordSerializer class BookViewSet(viewsets.ModelViewSet): 图书视图集 queryset Book.objects.all() filter_backends [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter] filterset_fields [category, available] search_fields [title, author, isbn] ordering_fields [title, author, price, created_at] def get_serializer_class(self): 根据动作选择不同的序列化器 if self.action list: return BookListSerializer return BookDetailSerializer def get_permissions(self): 根据动作设置权限 if self.action in [create, update, partial_update, destroy]: permission_classes [IsAdminUser] else: permission_classes [IsAuthenticated] return [permission() for permission in permission_classes] action(detailTrue, methods[post]) def borrow(self, request, pkNone): 借阅图书 book self.get_object() user request.user # 创建借阅记录 borrow_record BorrowRecord.objects.create( bookbook, useruser, due_daterequest.data.get(due_date) ) # 更新图书库存 if book.stock 0: book.stock - 1 if book.stock 0: book.available False book.save() serializer BorrowRecordSerializer(borrow_record) return Response(serializer.data, statusstatus.HTTP_201_CREATED) action(detailTrue, methods[post]) def return_book(self, request, pkNone): 归还图书 book self.get_object() user request.user # 查找未归还的借阅记录 borrow_record BorrowRecord.objects.filter( bookbook, useruser, statusborrowed ).first() if not borrow_record: return Response( {error: 没有找到对应的借阅记录}, statusstatus.HTTP_404_NOT_FOUND ) # 更新借阅记录 borrow_record.status returned borrow_record.return_date request.data.get(return_date) borrow_record.save() # 更新图书库存 book.stock 1 book.available True book.save() serializer BorrowRecordSerializer(borrow_record) return Response(serializer.data) class BorrowRecordViewSet(viewsets.ReadOnlyModelViewSet): 借阅记录视图集只读 serializer_class BorrowRecordSerializer permission_classes [IsAuthenticated] filter_backends [DjangoFilterBackend, filters.OrderingFilter] filterset_fields [status] ordering_fields [borrow_date, due_date] def get_queryset(self): 用户只能查看自己的借阅记录 return BorrowRecord.objects.filter(userself.request.user)配置路由# books/urls.py from django.urls import path, include from rest_framework.routers import DefaultRouter from .views import BookViewSet, BorrowRecordViewSet router DefaultRouter() router.register(rbooks, BookViewSet, basenamebook) router.register(rborrow-records, BorrowRecordViewSet, basenameborrow-record) urlpatterns [ path(api/, include(router.urls)), ] # 项目主路由 # library/urls.py from django.contrib import admin from django.urls import path, include urlpatterns [ path(admin/, admin.site.urls), path(, include(books.urls)), ]第五步API认证与权限控制安全是API设计的重中之重。DRF提供了多种认证方式我们选择JWT作为认证方案# 安装JWT支持 pip install djangorestframework-simplejwt # settings.py中添加配置 REST_FRAMEWORK { DEFAULT_AUTHENTICATION_CLASSES: [ rest_framework_simplejwt.authentication.JWTAuthentication, ], DEFAULT_PERMISSION_CLASSES: [ rest_framework.permissions.IsAuthenticated, ], } # urls.py中添加JWT路由 from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView urlpatterns [ path(api/token/, TokenObtainPairView.as_view(), nametoken_obtain_pair), path(api/token/refresh/, TokenRefreshView.as_view(), nametoken_refresh), # ... 其他路由 ]JWTJSON Web Token是目前最流行的API认证方案之一。它由三部分组成头部Header、载荷Payload和签名Signature。JWT的工作流程如下客户端使用用户名密码登录服务器验证后生成JWT服务器将JWT返回给客户端客户端在后续请求中携带JWT通常放在Authorization头中服务器验证JWT的签名确认用户身份第六步API文档与测试DRF自动生成可交互的API文档让测试变得简单# 安装API文档支持 pip install drf-yasg # 配置文档生成 # urls.py from rest_framework import permissions from drf_yasg.views import get_schema_view from drf_yasg import openapi schema_view get_schema_view( openapi.Info( title图书管理系统API, default_versionv1, description图书馆图书管理系统的RESTful API文档, contactopenapi.Contact(emailcontactlibrary.com), ), publicTrue, permission_classes[permissions.AllowAny], ) urlpatterns [ path(swagger/, schema_view.with_ui(swagger, cache_timeout0), nameschema-swagger-ui), path(redoc/, schema_view.with_ui(redoc, cache_timeout0), nameschema-redoc), # ... 其他路由 ]访问/swagger/或/redoc/即可看到完整的API文档。DRF的自动文档界面让API测试变得直观第七步性能优化与高级特性1. 缓存策略对于频繁查询但更新不频繁的数据使用缓存可以显著提升性能# settings.py CACHES { default: { BACKEND: django.core.cache.backends.redis.RedisCache, LOCATION: redis://127.0.0.1:6379/1, } } # views.py中使用缓存 from django.utils.decorators import method_decorator from django.views.decorators.cache import cache_page from django.views.decorators.vary import vary_on_headers class BookViewSet(viewsets.ModelViewSet): # ... method_decorator(cache_page(60 * 15)) # 缓存15分钟 method_decorator(vary_on_headers(Authorization, Accept-Language)) def list(self, request, *args, **kwargs): return super().list(request, *args, **kwargs)2. 异步任务处理对于耗时操作如发送邮件、生成报表使用Celery进行异步处理# tasks.py from celery import shared_task from django.core.mail import send_mail shared_task def send_borrow_notification(user_email, book_title, due_date): 异步发送借阅通知邮件 subject f借阅提醒《{book_title}》即将到期 message f您借阅的《{book_title}》将于{due_date}到期请及时归还。 send_mail(subject, message, noreplylibrary.com, [user_email]) # views.py中调用异步任务 action(detailTrue, methods[post]) def borrow(self, request, pkNone): # ... 借阅逻辑 # 异步发送通知邮件 send_borrow_notification.delay( user.email, book.title, borrow_record.due_date.strftime(%Y-%m-%d) )3. 限流与防护防止API被恶意请求# settings.py REST_FRAMEWORK { DEFAULT_THROTTLE_CLASSES: [ rest_framework.throttling.AnonRateThrottle, rest_framework.throttling.UserRateThrottle ], DEFAULT_THROTTLE_RATES: { anon: 100/day, # 匿名用户每天100次 user: 1000/day, # 认证用户每天1000次 } }常见问题与解决方案问题1N1查询问题当序列化器包含外键关联时可能会出现N1查询问题。解决方案是使用select_related和prefetch_relatedclass BookViewSet(viewsets.ModelViewSet): def get_queryset(self): # 优化查询减少数据库访问次数 return Book.objects.select_related(publisher).prefetch_related(authors).all()问题2API版本管理随着业务发展API需要升级但又要保持向后兼容# urls.py from django.urls import path, include from rest_framework.routers import DefaultRouter router_v1 DefaultRouter() router_v1.register(rbooks, BookViewSetV1, basenamebook-v1) router_v2 DefaultRouter() router_v2.register(rbooks, BookViewSetV2, basenamebook-v2) urlpatterns [ path(api/v1/, include(router_v1.urls)), path(api/v2/, include(router_v2.urls)), ]问题3复杂查询参数处理对于复杂的查询需求可以使用django-filter的高级功能# filters.py import django_filters from .models import Book class BookFilter(django_filters.FilterSet): min_price django_filters.NumberFilter(field_nameprice, lookup_exprgte) max_price django_filters.NumberFilter(field_nameprice, lookup_exprlte) author django_filters.CharFilter(field_nameauthor, lookup_expricontains) published_after django_filters.DateFilter(field_namepublish_date, lookup_exprgte) class Meta: model Book fields [category, available]最佳实践总结遵循RESTful原则资源使用名词操作使用HTTP动词合理的错误处理返回明确的HTTP状态码和错误信息版本控制从项目开始就规划API版本文档先行使用Swagger/OpenAPI规范编写API文档监控与日志记录API访问日志监控性能指标安全第一使用HTTPS、验证输入、限制访问频率测试覆盖编写单元测试和集成测试确保API稳定性通过本文的实战指南你已经掌握了使用DRF构建企业级RESTful API的核心技能。记住好的API设计不仅是技术的实现更是对业务需求的深刻理解。在实践中不断优化你的API将成为连接前后端的坚实桥梁。【免费下载链接】Python-100-DaysPython - 100天从新手到大师项目地址: https://gitcode.com/GitHub_Trending/py/Python-100-Days创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考