如何在DRF中让同一URL支持ID或唯一字段Name操作对象且不重复代码?
这事儿很简单,不用写重复代码,只要调整下URL路径并重写视图的get_object方法就行,具体步骤如下:
解决方案
1. 调整URL路径参数
首先把urls.py里的路径从UUID专属参数改成通用字符串参数,这样它能同时接收UUID格式的ID和普通字符串的name:
path('<str:identifier>/', InstanceDetail.as_view()),
2. 重写视图的get_object方法
在你的InstanceDetail视图类里,重写get_object方法,让它自动判断传入的参数是ID还是name,然后对应查询:
from django.http import Http404 import uuid class InstanceDetail(generics.RetrieveUpdateAPIView): permission_classes = [IsAuthenticated, ] queryset = Instance.objects.all() serializer_class = InstanceSerializer def get_object(self): identifier = self.kwargs.get('identifier') # 先尝试按UUID格式的ID查找 try: uuid_id = uuid.UUID(identifier) return self.queryset.get(id=uuid_id) except (ValueError, Instance.DoesNotExist): # 不是有效UUID或对应ID不存在,再按name查找 try: return self.queryset.get(name=identifier) except Instance.DoesNotExist: raise Http404("指定的实例不存在")
为什么这样可行?
DRF的RetrieveUpdateAPIView默认靠pk参数调用get_object获取实例,我们把URL参数改成通用的identifier后,自定义get_object的逻辑:
- 先尝试解析参数为UUID:如果成功,就用模型的
id字段查询 - 解析失败(说明是name)或者ID对应实例不存在,就用
name字段查询 - 两种方式都找不到的话,抛出
Http404,和DRF默认行为保持一致
这样就实现了同一个URL同时支持ID和name访问,完全复用原有视图的所有逻辑,没有冗余代码。
内容的提问来源于stack exchange,提问作者Zat42
相关产品推荐
相关产品推荐

