如何让Django Endpoint同时支持UUID与Slug两种字段查询?
实现Django接口同时支持UUID和Slug访问详情页
要让你的Post接口同时支持通过UUID(如localhost:9000/post/f18e8017-ebbc-432d-b1c6-1ff23737a744)和Slug(如localhost:9000/post/post-title)访问详情页,按以下步骤修改代码:
1. 序列化器调整
原序列化器固定了lookup_field = 'slug',会限制Hyperlinked字段的指向逻辑,移除该固定配置即可:
class PostSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Post fields = [ 'id', 'post_title', 'text', 'slug', ] # 移除 lookup_field = 'slug',由视图控制lookup逻辑
2. 视图重写核心查询逻辑
在PostViewSet中重写get_object方法,根据传入参数的格式判断是UUID还是Slug,再执行对应查询:
import uuid from django.shortcuts import get_object_or_404 from rest_framework import mixins, viewsets class PostViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, viewsets.GenericViewSet): queryset = Post.objects.all().order_by('id') serializer_class = PostSerializer ordering = ['id'] def get_object(self): queryset = self.get_queryset() pk = self.kwargs.get('pk') # 尝试匹配UUID格式 try: uuid.UUID(pk) return get_object_or_404(queryset, id=pk) except ValueError: # 非UUID则按slug查询 return get_object_or_404(queryset, slug=pk)
3. 路由配置适配
原DefaultRouter生成的详情路由默认匹配Slug格式,需调整路由规则使其支持任意字符串(兼容UUID和Slug):
from rest_framework import routers from django.urls import path, include router = routers.DefaultRouter() # 注册视图集时指定匹配规则为任意字符串,覆盖默认的slug正则 router.register(r'post', PostViewSet, basename='post', lookup_value_regex='[^/]+') urlpatterns = [ path(r'', include(router.urls)), ]
关键说明:
- 利用
uuid.UUID(pk)的异常捕获判断参数格式,确保UUID查询的准确性 - 因
slug字段设置了unique=True,两种查询方式都能保证返回唯一结果 - 若需保留Hyperlinked字段的正确指向,可在序列化器中自定义字段生成对应URL,上述修改已满足基础访问需求
内容的提问来源于stack exchange,提问作者Jdam0xff
相关产品推荐
相关产品推荐

