如何用DRF构建API,实现JWT校验及带参数的多数据端点服务
Django API开发:JWT检查、参数获取与端点设计指南
Hey there! Let's break down your questions step by step since you're new to building APIs in Django—no worries, we'll get this sorted out clearly.
1. 如何提取JWT令牌?
JWT令牌通常是通过请求头的Authorization字段传递的,格式一般是Bearer <your-token-here>。在Django中,你可以直接从request.META中获取这个字段,不需要额外的端点来接收它(除非你的客户端是通过POST body发送,但这不符合标准API设计规范)。
举个简单的提取和存在性检查逻辑:
def check_jwt_exists(request): auth_header = request.META.get('HTTP_AUTHORIZATION') # 只检查令牌是否存在且格式正确,不验证签名(符合你的需求) return auth_header and auth_header.startswith('Bearer ')
你可以在需要的视图里调用这个函数,判断是否允许POST操作。
2. ID参数的获取方式
ID参数的获取分两种常见场景:
- URL路径参数:比如你的端点是
../api/contact/<int:contact_id>/,那么在视图函数里可以直接把ID作为参数接收:
对应的urls.py配置:@api_view(['GET', 'POST']) def contact_detail(request, contact_id): # contact_id就是URL里的ID值,直接用它查询数据即可 passpath('api/contact/<int:contact_id>/', views.contact_detail, name='contact-detail') - 查询参数:如果ID是通过URL的查询字符串传递(比如
../api/contact/?id=123),可以用request.GET获取:contact_id = request.GET.get('id') # 记得处理参数不存在的情况,比如返回400错误
3. 是否需要单独的POST端点?
完全不需要!你可以在同一个端点里处理GET和POST请求,用@api_view(['GET', 'POST'])装饰器,然后根据request.method分支处理逻辑。这样更符合RESTful设计规范,也让你的API结构更简洁。
4. 序列化与数据保存完整示例
结合上面的JWT检查和参数获取,给你一个完整的视图示例,以contact端点为例:
首先创建序列化器(serializers.py):
from rest_framework import serializers from .models import Contact class ContactSerializer(serializers.ModelSerializer): class Meta: model = Contact fields = '__all__' # 或者指定你需要的字段,比如['id', 'name', 'email']
然后在views.py中编写视图:
from rest_framework.response import Response from rest_framework.decorators import api_view from rest_framework import status from .models import Contact from .serializers import ContactSerializer def check_jwt_exists(request): auth_header = request.META.get('HTTP_AUTHORIZATION') return auth_header and auth_header.startswith('Bearer ') @api_view(['GET', 'POST']) def contact_list(request): # 处理GET请求:返回所有联系人数据 if request.method == 'GET': contacts = Contact.objects.all() serializer = ContactSerializer(contacts, many=True) return Response(serializer.data) # 处理POST请求:检查JWT后保存数据 elif request.method == 'POST': if not check_jwt_exists(request): return Response({"error": "JWT token is required for POST requests"}, status=status.HTTP_403_FORBIDDEN) serializer = ContactSerializer(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) # 带ID参数的详情视图(支持查询、编辑、删除) @api_view(['GET', 'PUT', 'DELETE']) def contact_detail(request, contact_id): try: contact = Contact.objects.get(pk=contact_id) except Contact.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) if request.method == 'GET': serializer = ContactSerializer(contact) return Response(serializer.data) # 编辑或删除操作也可以添加JWT检查,按需调整 elif request.method == 'PUT': if not check_jwt_exists(request): return Response({"error": "JWT token is required"}, status=status.HTTP_403_FORBIDDEN) serializer = ContactSerializer(contact, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
然后在urls.py中配置多个端点:
from django.urls import path from . import views urlpatterns = [ path('api/contact/', views.contact_list, name='contact-list'), path('api/contact/<int:contact_id>/', views.contact_detail, name='contact-detail'), path('api/qualifications/', views.qualification_list, name='qualification-list'), # 按照同样的逻辑添加其他端点的配置即可 ]
小提示:简化重复的JWT检查逻辑
如果多个视图都需要检查JWT,你可以把这个逻辑做成一个自定义装饰器,避免重复代码:
from functools import wraps from rest_framework.response import Response from rest_framework import status def require_jwt(view_func): @wraps(view_func) def wrapper(request, *args, **kwargs): auth_header = request.META.get('HTTP_AUTHORIZATION') if not auth_header or not auth_header.startswith('Bearer '): return Response({"error": "JWT token is required"}, status=status.HTTP_403_FORBIDDEN) return view_func(request, *args, **kwargs) return wrapper
然后在需要的视图上直接使用:
@api_view(['POST']) @require_jwt def create_contact(request): # 处理POST逻辑即可,无需再写JWT检查代码 pass
内容的提问来源于stack exchange,提问作者Dhruv
相关产品推荐
相关产品推荐

