You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django DRF笔记CRUD API更新接口request类型报错排查

问题描述

开发Django REST Framework笔记CRUD API时,笔记更新功能无法正常运行,访问更新接口路径/Note/update/4/时触发500内部服务错误。

相关代码

tools.py

from .models import Note
from .serializers import NoteSerializer
from rest_framework.response import Response
from django.shortcuts import get_object_or_404

def getNoteslist(request):
    notes=Note.objects.all().order_by('-updated')
    serializer=NoteSerializer(notes, many=True)
    return Response(serializer.data)

def NoteDetail(request, pk):
    notedetail=get_object_or_404(Note,id=pk)
    serializer=NoteSerializer(notedetail, many=False)
    return Response(serializer.data)

def createNote(request):
    data=request.data
    note=Note.objects.create(
    title=data['title'],
    body=data['body']
    )
    serializer=NoteSerializer(note, many=False)
    return Response(serializer.data)

def updateNote(request, pk):
    note=Note.objects.get(id=pk)
    serializer=NoteSerializer(instance=note, data=request.data)
    if serializer.is_valid():
        serializer.save()
    return Response(serializer.data)

def delete(request, pk):
    note=get_object_or_404(Note,id=pk)
    note.delete()
    return Response('Note is deleted!')

views.py

from .models import Note
from .tools import getNoteslist,NoteDetail,updateNote,createNote,delete
from rest_framework.decorators import api_view

@api_view(['GET'])
def getNotes(request):
    return getNoteslist(request)
@api_view(['POST'])  
def createNotes(request):
    return createNote(request)

@api_view(['GET'])
def getNote(request,pk):
    return NoteDetail(request, pk)

@api_view(['POST'])   
def updateNote(request, pk):
    return updateNote(request, pk)

@api_view(['DELETE'])
def delNote(request, pk):
    return delete(request, pk)

urls.py

from django.urls import path
from . import views
from rest_framework.documentation import include_docs_urls
from rest_framework_swagger.views import get_swagger_view

schema_view=get_swagger_view(title='NOTE TAKING APi')
API_TITLE='NOTE TAKING APi'
API_DESCRIPTION='A note taking API for creating and editing notes.'

urlpatterns=[
path('',views.getNotes,name='Notes'),
path('create/',views.createNotes,name='Notes'),
path('<int:pk>/',views.getNote,name='note'),
path('update/<int:pk>/',views.updateNote,name='note'),
path('delete/<int:pk>/',views.delNote,name='note'),
path('docs/',include_docs_urls(title=API_TITLE, 
description=API_DESCRIPTION)),
path('swagger-docs/',schema_view)
]
报错信息
Internal Server Error: /Note/update/4/
Traceback (most recent call last):
  File "C:\Users\Hp\anaconda3\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\Users\Hp\anaconda3\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\Hp\anaconda3\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Hp\anaconda3\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "C:\Users\Hp\anaconda3\lib\site-packages\django\views\generic\base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Users\Hp\anaconda3\lib\site-packages\rest_framework\views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "C:\Users\Hp\anaconda3\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "C:\Users\Hp\anaconda3\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
    raise exc
  File "C:\Users\Hp\anaconda3\lib\site-packages\rest_framework\views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "C:\Users\Hp\anaconda3\lib\site-packages\rest_framework\decorators.py", line 50, in handler
    return func(*args, **kwargs)
  File "C:\Users\Hp\anaconda3\DJANGO\api\NoteTaking\Note\views.py", line 20, in updateNote  
    return updateNote(request, pk)
  File "C:\Users\Hp\anaconda3\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "C:\Users\Hp\anaconda3\lib\site-packages\django\views\generic\base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Users\Hp\anaconda3\lib\site-packages\rest_framework\views.py", line 492, in dispatch
    request = self.initialize_request(request, *args, **kwargs)
  File "C:\Users\Hp\anaconda3\lib\site-packages\rest_framework\views.py", line 391, in initialize_request
    return Request(
  File "C:\Users\Hp\anaconda3\lib\site-packages\rest_framework\request.py", line 154, in __init__
    assert isinstance(request, HttpRequest), (
AssertionError: The `request` argument must be an instance of `django.http.HttpRequest`, not `rest_framework.request.Request`.
报错原因

核心问题是函数命名冲突导致递归调用:

  • 你在views.py中从tools模块导入了名为updateNote的工具函数,随后又在同文件定义了同名的视图函数updateNote,后者会覆盖前者的引用。
  • 当请求命中视图函数时,函数内部执行return updateNote(request, pk)时,调用的不是tools里的业务逻辑函数,而是被@api_view装饰的视图函数本身,形成递归调用。
  • 第一次进入视图时,@api_view装饰器已经把原生Django HttpRequest对象包装成了DRF的Request对象;递归调用时,这个DRF Request对象被再次传给被@api_view装饰的函数,而装饰器初始化逻辑要求传入的必须是原生HttpRequest对象,因此触发断言错误。

代码还存在3个潜在问题:

  • 更新接口仅允许POST方法,不符合RESTful规范,更新操作应使用PUT/PATCH方法
  • tools中更新逻辑直接用Note.objects.get()查询对象,传入不存在的pk时会抛出DoesNotExist异常,没有做404处理
  • 序列化器校验失败时没有返回错误信息,直接返回serializer.data无法定位校验问题
修复方案
  • 解决命名冲突:给导入的工具函数加别名,避免同名覆盖,同时修改视图允许的请求方法,调整views.py对应代码:
    # 导入时给工具函数起别名
    from .tools import getNoteslist,NoteDetail,updateNote as tool_updateNote,createNote,delete
    
    # 其余视图逻辑保持不变
    @api_view(['PUT', 'PATCH']) # 允许更新场景常用的PUT、PATCH请求方法
    def updateNote(request, pk):
        return tool_updateNote(request, pk)
    
  • 完善tools.py中的更新逻辑,补全404处理和校验错误返回:
    def updateNote(request, pk):
        # 替换直接get查询,不存在的对应id直接返回404
        note=get_object_or_404(Note,id=pk)
        serializer=NoteSerializer(instance=note, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        # 校验失败返回400状态码和具体错误信息
        return Response(serializer.errors, status=400)
    
  • 接口测试时,使用PUT或PATCH方法请求/Note/update/4/路径,传入需要更新的title、body字段参数即可正常完成更新操作。

内容的提问来源于stack exchange,提问作者Captain Leon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 23:12:19