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

Django REST Framework POST请求405方法不允许问题求助

问题:POST请求创建Track资源时返回405 Method Not Allowed

问题详情

开发类Spotify后端服务时,调用http://127.0.0.1:8000/music/add/接口发送POST请求创建Track资源,服务器返回405 Method Not Allowed错误。

请求示例

POST http://127.0.0.1:8000/music/add/
Content-Type: application/json
Authorization: token 3e356c812614c3d4344e0d06773c27387b1e4c12

{
  "title": "Evil Ways", 
  "duration": "00:03:47", 
  "release_date": "2023-09-03", 
  "audio_file": "/media/tracks/Music_Library.musiclibrary.zip", 
  "artist": 2, 
  "album": 2, 
  "genre": 1
}

服务器响应

HTTP/1.1 405 Method Not Allowed
Date: Thu, 08 Feb 2024 09:11:56 GMT
Server: WSGIServer/0.2 CPython/3.9.0
Content-Type: application/json
Vary: Accept, Cookie
Allow: OPTIONS, GET
X-Frame-Options: DENY
Content-Length: 41

{
  "detail": "Method \"POST\" not allowed."
}

相关代码

music应用的urls.py

from django.urls import path
from . import views

urlpatterns = [
    # path for get requests
    path('',views.get_all_tracks, name='get_all_tracks'),
    path('<str:track_name>/', views.get_tracks_by_name, name='get_tracks_by_name'),
    path('add/', views.add_track),
]

项目根urls.py

from django.contrib import admin
from django.urls import path, include
from .views import (
    home_page,
)

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', home_page),
    
    path('auth/', include('authentication.urls')),
    path('music/', include('music.urls')),
    path('album/', include('album.urls')),
    path('artist/', include('artist.urls')),
    path('playlist/', include('playlist.urls'))
]

views.py中的add_track视图

from django.shortcuts import render
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator

from .models import Track, Artist, Genre, Album
from .serializers import TrackSerializer

from rest_framework.decorators import api_view, authentication_classes , permission_classes
from rest_framework.authentication import SessionAuthentication, TokenAuthentication
from rest_framework.permissions import IsAuthenticated

# ... other views


@api_view(['GET', 'POST'])
@authentication_classes([SessionAuthentication, TokenAuthentication])
@permission_classes([IsAuthenticated])
def add_track(request): 
    if request.method =="POST":
        title = request.data.get('title')
        artist_id = request.data.get('artist')
        album_id = request.data.get('album')
        duration = request.data.get('duration')
        release_date = request.data.get('release_date')
        genre_id = request.data.get('genre')
        audio_file = request.data.get('audio_file')

            # Create a new Track object
        track = Track.objects.create(
            title=title,
            artist_id=artist_id,
            album_id=album_id,
            duration=duration,
            release_date=release_date,
            genre_id=genre_id,
            audio_file=audio_file
        )

            # Return a JSON response with the created track data
        data = {
                'title': track.title,
                'artist': track.artist.name,
                'album': track.album.title,
                'duration': str(track.duration),
                'release_date': str(track.release_date),
                'genre': track.genre.name,
                'audio_file': track.audio_file.url,  # Assuming 'audio_file' is a FileField
            }
        return JsonResponse(data, status=201)
    else:
        return "this page needs a POST request"

models.py中的Track模型

from django.db import models
from artist.models import Artist
from album.models import Album

class Genre(models.Model):
    name = models.CharField(max_length=100, unique=True)

    def __str__(self):
        return self.name

class Track(models.Model):
    title = models.CharField(max_length=200)
    artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
    album = models.ForeignKey(Album, on_delete=models.CASCADE)
    duration = models.DurationField()
    release_date = models.DateField()
    genre = models.ForeignKey(Genre, on_delete=models.CASCADE)
    audio_file = models.FileField(upload_to='tracks/')
    # Add other track-related fields (e.g., lyrics)

    def __str__(self):
        return self.title

解决方案

1. 修复URL路由顺序问题

当前music/urls.py中,动态路由path('<str:track_name>/', ...)会优先匹配music/add/请求(add会被当作track_name参数),导致请求被路由到仅支持GET的get_tracks_by_name视图。调整路由顺序,将更具体的add/路由放在动态路由前面:

urlpatterns = [
    path('',views.get_all_tracks, name='get_all_tracks'),
    path('add/', views.add_track),  # 移到动态路由前
    path('<str:track_name>/', views.get_tracks_by_name, name='get_tracks_by_name'),
]

2. 修复视图的非POST响应格式

原视图在非POST请求时返回字符串,不符合DRF响应规范,改为返回DRF的Response对象:

from rest_framework.response import Response

@api_view(['GET', 'POST'])
@authentication_classes([SessionAuthentication, TokenAuthentication])
@permission_classes([IsAuthenticated])
def add_track(request): 
    if request.method =="POST":
        # 原POST逻辑不变
    else:
        return Response({"detail": "该接口仅支持POST请求"}, status=400)

3. 用序列化器验证数据(推荐)

直接使用request.data.get()创建模型易导致数据错误,建议用DRF序列化器做数据校验:

@api_view(['GET', 'POST'])
@authentication_classes([SessionAuthentication, TokenAuthentication])
@permission_classes([IsAuthenticated])
def add_track(request): 
    if request.method =="POST":
        serializer = TrackSerializer(data=request.data)
        if serializer.is_valid():
            track = serializer.save()
            data = {
                'title': track.title,
                'artist': track.artist.name,
                'album': track.album.title,
                'duration': str(track.duration),
                'release_date': str(track.release_date),
                'genre': track.genre.name,
                'audio_file': track.audio_file.url,
            }
            return Response(data, status=201)
        return Response(serializer.errors, status=400)
    else:
        return Response({"detail": "该接口仅支持POST请求"}, status=400)

4. 调整音频文件传递方式(可选)

请求中audio_file字段传递的是本地路径,若为文件上传场景,需改用multipart/form-data格式发送请求,传递实际文件对象而非路径字符串。

内容的提问来源于stack exchange,提问作者Chanakya Sharma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 08:34:51