Django REST Framework为action传参时出现404页面未找到错误
首先看你的404错误,核心原因有两个:一是自定义action的url_path写法导致生成的URL模式多了冗余斜杠,二是detail=False的设置和你调用self.get_object()的逻辑冲突。
1. 修正URL路径匹配问题
你的@action装饰器里url_path='delete_phone/<phone_pk>/'末尾加了斜杠,而DRF的Router默认会给URL添加末尾斜杠,这就导致生成的URL模式变成了delete_phone/<phone_pk>//$(两个连续斜杠),自然匹配不上你请求的delete_phone/1/。
把url_path改成不带末尾斜杠的格式即可:
@action(methods=['delete'], detail=False, url_path='delete_phone/<phone_pk>')
如果需要限制参数为数字,也可以用正则写法:
@action(methods=['delete'], detail=False, url_path='delete_phone/(?P<phone_pk>\d+)')
2. 修正self.get_object()的逻辑矛盾
你设置了detail=False,这表示这个action是集合级别的(对应整个contacts列表),此时请求URL里不会包含Contact对象的pk参数,但你调用了self.get_object()——这个方法是用来获取单个对象的,它需要从URL里拿到pk才能查询,所以即使URL匹配上了,后续也会抛出异常。
根据你的业务需求,分两种场景优化:
场景A:直接删除指定phone_pk的电话记录
如果你的需求是删除某个独立的电话记录,不需要关联特定联系人,那去掉self.get_object(),直接查询Phone模型即可:
from django.shortcuts import get_object_or_404 from .models import Phone # 假设你有对应的Phone模型 @action(methods=['delete'], detail=False, url_path='delete_phone/<phone_pk>') def delete_phone(self, request, phone_pk=None): phone = get_object_or_404(Phone, pk=phone_pk) phone.delete() return Response({'status': 'success'})
场景B:删除指定联系人下的某条电话记录
如果是要删除某个联系人(通过pk定位)下的指定电话,那应该把detail设为True,这样URL会变成contacts/<contact_pk>/delete_phone/<phone_pk>/,此时就能正确获取到目标联系人对象:
from django.shortcuts import get_object_or_404 @action(methods=['delete'], detail=True, url_path='delete_phone/<phone_pk>') def delete_phone(self, request, pk=None, phone_pk=None): contact = self.get_object() # 这里能拿到pk对应的Contact对象 # 假设Contact和Phone是一对多关系,比如contact.phones是关联的电话集合 phone = get_object_or_404(contact.phones, pk=phone_pk) phone.delete() return Response({'status': 'success'})
此时请求URL需要调整为DELETE: http://url/api/contacts/<contact_pk>/delete_phone/1/,其中<contact_pk>是目标联系人的ID。
3. 验证修改效果
修改后重启服务,查看错误页面的“尝试过的URL模式”,应该会显示正确的格式(比如api/ ^contacts/delete_phone/(?P<phone_pk>\d+)/$),此时再发起请求就能正常匹配了。
内容的提问来源于stack exchange,提问作者Anuj TBE

