【问题标题】:Django REST API update view returns http 405Django REST API 更新视图返回 http 405
【发布时间】:2020-09-23 13:56:09
【问题描述】:

我正在尝试使用 django 后端构建单页应用程序 (Vue)。这是一个练习 Vue + Django Rest Framework 的非常简单的应用程序。该应用程序允许用户创建、删除和查看(列出)故事(只是标题、日期时间和内容(简单的文本)),这很好用。我现在也在尝试实现编辑功能,但我收到关于 CORS 标头的错误。

我的后端代码非常简单。 设置.py

# relevant parts of settings.py
INSTALLED_APPS = [
    ...,
    'rest_framework',
    'corsheaders'
]

MIDDLEWARE = [
    ...,
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
]

CORS_ALLOWED_ORIGINS = [
    "http://localhost:8080",
]
CORS_ALLOW_METHODS = (
    'GET',
    'POST',
    'PUT',
    'PATCH',
    'DELETE',
    'OPTIONS'
)

urls.py:

urlpatterns = [
    path('', views.StoryList.as_view(), name='stories'),
    path('<int:pk>/', views.StoryDetail.as_view(), name='story'),
    path('delete/<int:pk>/', views.StoryDetail.as_view(), name='delete_story'),
    path('update/<int:pk>/', views.StoryDetail.as_view(), name='update_story')
]

views.py:

from django.shortcuts import render
from django.http import HttpResponse, Http404
from rest_framework import generics
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

from .models import Story
from .serializers import StorySerializer

class StoryList(APIView):
    def get(self, request, format=None):
        stories = Story.objects.all()
        serializer = StorySerializer(stories, many=True)
        return Response(serializer.data)
    
    def post(self, request, format=None):
        serializer = StorySerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST)

class StoryDetail(APIView):
    def get_object(self, pk):
        try:
            return Story.objects.get(pk=pk)
        except Story.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        story = self.get_object(pk)
        serializer = StorySerializer(story)
        return Response(serializer.data)

    def delete(self, request, pk, format=None):
        story = self.get_object(pk)
        story.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

    def update(self, request, pk, *args, **kwargs):
        story = self.get_object(pk)
        print(story)
        serializer = StorySerializer(story)
        if serializer.is_valid():
            serializer.save()
            return Response(status=status.HTTP_201_CREATED, data=serializer.data)
        return Response(status=status.HTTP_400_BAD_REQUEST, data='Wrong parameters')

所以方法 get 和 delete 在详细视图上工作正常。并且在列表视图上列出和创建也可以正常工作。只有更新方法不起作用。我得到的错误:

405 Method Not Allowed

响应头确实没有将其定义为允许:

Allow: GET, DELETE, HEAD, OPTIONS

但我以为我已经在 settings.py 中定义了所有内容

如有必要,我的前端代码(相关部分):

<template>
  <form
    id="add_story"
    action="http://localhost:8000"
    method="post"
    @submit.prevent="saveStory">

    <input
      id="story_id"
      type="hidden"
      v-model="value.id"
      required />

    <input
      id="story_datetime"
      type="hidden"
      v-model="value.datetime"
      required />

    <b-form-input
      id="story_title"
      v-model="value.title"
      required>
    </b-form-input>
          
    <b-form-textarea
      id="story"
      v-model="value.content">
    </b-form-textarea>

    <b-button type="submit" variant="primary">Submit</b-button>
  </form>
</template>

<script>
export default {
  name: 'Story-form',
  props: {
    // gets the data from the parent which works fine
    value: {
      type: Object,
      required: true
    },
  },
  methods: {
    async saveStory () {
      // if value.id is set: update story
      const now = new Date();
      if (this.value.datetime == ""){
        this.value.datetime = now.toISOString();
      }
      const story_data = {
        // id: this.value.id,
        title: this.value.title,
        content: this.value.content,
        datetime: this.value.datetime
      };
      let send_method = (story_data.id === null) ? "POST" : "PUT";
      let send_url = (story_data.id === null) ? "http://localhost:8000/" : "http://localhost:8000/update/" + String(this.value.id) + "/";
      await fetch(send_url, {
        method: send_method,
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(story_data)
      }).then( (response) => {
        if (!response.ok){
          console.log(response);
          this.error = false;
        } else {
          // reset everything back to normal
        }
      }).catch(e => {
        console.log(e);
      });
    }
  }
}
</script>

关于如何解决这个问题的任何想法。我不想使用视图集,因为我试图理解 DRF,并且视图集在幕后发生了太多事情。

【问题讨论】:

    标签: django rest vue.js django-rest-framework vuejs2


    【解决方案1】:

    方法名称应该是 patch(...)put(...) 而不是 update(...)

    因为,APIView 类没有任何完整的方法来查找 update() 方法,但通用 API 可以。

    【讨论】:

      猜你喜欢
      • 2021-01-14
      • 2016-04-29
      • 2015-08-31
      • 1970-01-01
      • 2013-12-28
      • 1970-01-01
      • 2015-11-26
      • 1970-01-01
      • 2019-02-27
      相关资源
      最近更新 更多