手把手搭 RESTful API:用 DRF 给业务系统开放接口实战
【免费下载链接】Python-100-DaysPython - 100天从新手到大师项目地址: https://gitcode.com/GitHub_Trending/py/Python-100-Days
假设你要给一套校园选课系统补数据出口:管理后台要拉取课程和教师列表,移动端要查学生档案。总不能为每块屏幕各写一套 HTML 吧?正确的做法是把数据按 RESTful 风格暴露成一组标准接口,让所有客户端共用同一套数据源。这正是 Python-100-Days 里 Django REST Framework(下称 DRF)章节解决的问题。你可以把 REST 理解成给数据资源定的一套"点菜规则":菜名(URI)唯一,动作(HTTP 方法)固定——浏览菜单是查询,下单是新建,改单是更新,退菜是删除。规则定了,前端、App、小程序谁来"点菜"都听得懂。
5 分钟跑通第一个接口:装包、三行配置、一个视图
最短路径只有四步,全程不超过 5 分钟。
第 1 步,装包。
pip install djangorestframework第 2 步,在 settings.py 里注册应用。
INSTALLED_APPS = [ 'rest_framework', # ... 其余应用省略 ... ]第 3 步,写一个能返回 JSON 的视图。
from rest_framework.decorators import api_view from rest_framework.response import Response from .models import Subject @api_view(['GET']) def show_subjects(request): subjects = Subject.objects.all().order_by('no') return Response(SubjectSerializer(subjects, many=True).data)第 4 步,挂上 URL,启动服务。
# urls.py(一行即可) path('api/subjects/', show_subjects),浏览器打开http://127.0.0.1:8000/api/subjects/,你会看到一个 DRF 自带的调试页面,上面直接展示返回的 JSON:
看到这里,一个接口就算"跑起来了"。注意一个新手最容易踩的雷:@api_view视图必须返回 DRF 的Response而不是 Django 原生的HttpResponse,否则浏览器里那个漂亮的调试页面不会出现,直接吐裸数据。
💡 提示:这个调试页面不只是"好看",它还能手工发 POST/PUT 请求,联调期能顶半个 Postman。
拆解 DRF 的四个零件:序列化器、视图、认证、分页过滤
跑通之后别急着堆接口,先把 DRF 拆成四个零件看清楚,后面写什么都快。
零件一:序列化器——Python 对象和 JSON 之间的翻译官
它解决什么问题。数据库里的模型对象不能直接塞进 HTTP 响应,总得有人"翻译"成前端认识的 JSON。序列化器(Serializer)就是干这个的,而且它是双向的:出参时把对象翻成 JSON,入参时把 JSON 翻回对象并顺带做校验。
怎么用。继承ModelSerializer,指定模型和字段即可:
class StudentSerializer(serializers.ModelSerializer): class Meta: model = Student fields = ('id', 'name', 'age') def validate_age(self, value): # 入参校验钩子 if value < 18: raise serializers.ValidationError('年龄必须大于18岁') return value常见坑。图省事写fields = '__all__',结果把密码、手机号这些敏感字段也吐给了前端。字段列表一定要显式声明,"少给"永远比"给多了再删"安全。
零件二:视图——一行 ViewSet 顶五个视图函数
它解决什么问题。一个资源的增删改查,用函数视图得写五段几乎一样的逻辑。
怎么用。直接上ModelViewSet,配合router注册,五个接口一次配齐:
class StudentViewSet(ModelViewSet): queryset = Student.objects.all() serializer_class = StudentSerializer # urls.py router = DefaultRouter() router.register(r'students', StudentViewSet) # 生成 /students/ 和 /students/{id}/路由生成后,方法语义天然贴合 REST:GET列表与详情、POST创建、PUT全量更新、PATCH局部更新、DELETE删除,动词和 URI 各管各的,谁也不用越位。这也是我直接推荐 ViewSet 而不建议你纠结函数视图还是类视图的原因——它把惯例固化了,新人不会写歪。
常见坑。只给queryset不配权限,等于接口裸奔;或者手动调用了 Django 原生的HttpResponse,绕过了 DRF 的解析器。
⚠️ 注意:DRF 视图里永远用Response返回数据,别混用 Django 原生的响应对象。
零件三:认证与权限——默认把门关上
它解决什么问题。REST 接口天生不记人——服务器不存会话,每个请求都得自己带"身份证"。认证(Authentication)负责"你是谁",权限(Permission)负责"你能不能干"。
怎么用。在 settings.py 里设全局默认值,之后所有接口自动生效:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', 'rest_framework.authentication.SessionAuthentication', ], 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ], }常见坑。开发期嫌登录麻烦,全局权限写AllowAny然后忘了改,上线即事故。宁可开发时走 Session 认证(登录一次就行),也别全局放开。
零件四:分页与过滤——别让列表接口拖垮数据库
它解决什么问题。queryset全量加载在生产环境等于自杀;前端要的往往是"第 3 页、按年龄排、只要计算机专业的"。
怎么用。全局分页两行配置,过滤和排序挂在 ViewSet 上:
REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 10, } # StudentViewSet 内追加 filter_backends = [DjangoFilterBackend, OrderingFilter] filterset_fields = ['major'] # 支持 ?major=cs ordering_fields = ['age', 'no'] # 支持 ?ordering=-age过滤功能来自django-filter包,记得pip install django-filter。
💡 提示:分页不是可选项,是列表接口的出厂配置。
上线前必做的四件事:JWT 认证、缓存、过滤排序、接口文档
本地跑通只是热身,真要交付,按下面这份清单过一遍。
1. 把认证升级为 JWT。JWT 本质是一个自包含的带签名凭证:里面装着用户标识和过期时间,外面套一层只有服务器知道的签名,服务端验签即可确认身份,不用存任何会话状态,加机器扩容毫无压力。
# 登录成功后签发 payload = {'userid': user.id, 'exp': datetime.utcnow() + timedelta(days=1)} token = jwt.encode(payload, settings.SECRET_KEY).decode() # 每次请求验签,失败即 401 data = jwt.decode(token, settings.SECRET_KEY) # 抛异常则拒绝PyJWT 安装命令是pip install pyjwt。
2. 给读多写少的接口加缓存。课程目录、教师名录这类几乎不变的数据,缓存 15 分钟能挡掉绝大多数数据库压力:
from django.utils.decorators import method_decorator from django.views.decorators.cache import cache_page @method_decorator(cache_page(60 * 15), name='list') class SubjectViewSet(ModelViewSet): ...3. 过滤排序别偷懒。上一条清单里讲过的filterset_fields和ordering_fields要真正落到 ViewSet 上,前端列表页的筛选框全靠它们。
4. 文档交给工具自动生成。别再手写接口表格了,前后端联调时手写文档永远滞后。上 drf-spectacular,一条配置就能自动生成 OpenAPI/Swagger 文档,模型一变文档跟着变。项目里的 94.网络API接口设计 也强调过同样的思路:文档要能跟上代码。
⚠️ 注意:缓存、限流、文档这三样,上线当天补的成本远高于开发期顺手补的成本。
接下来可以往这些方向挖
到这里,一个能返回 JSON、带认证分页、有文档的 DRF 接口已经立住了。再往前,这些方向值得逐个击破:
- 继续 Day46-60/55.RESTful架构和DRF进阶 的投票项目实战,把 ViewSet 的钩子方法(
perform_create、get_queryset)玩熟 - 研究 JWT 的失效难题:令牌签发后过期前无法作废,黑名单、短有效期加刷新令牌是两种主流解法
- 把序列化器、过滤、认证组合起来,独立设计一套完整的图书管理 API
- 用 Docker 把服务打包(项目 Day91-100 有专门的容器章节),体验"接口写对"到"部署跑稳"之间的最后一公里
【免费下载链接】Python-100-DaysPython - 100天从新手到大师项目地址: https://gitcode.com/GitHub_Trending/py/Python-100-Days
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考