web-dev-qa-db-ja.com

Django Rest Framework ModelViewSetのメソッドを削除します

以下のビューに対してAPIリクエストを実行するためにPostmanを使用して単一のManuscriptItemインスタンスを削除しようとしました:

class ManuscriptViewSet(viewsets.ModelViewSet):
    """Handles creating, reading and updating items."""

    authentication_classes = (TokenAuthentication,)
    serializer_class = serializers.ManuscriptItemSerializer
    permission_classes = (permissions.PostOwnManuscript, IsAuthenticated,)

    def perform_create(self, serializer):
        """Sets the user profile to the logged in user."""
        serializer.save(author=self.request.user)

    def get_queryset(self):
        """
        This view should return a list of all the manuscripts
        for the currently authenticated user.
        """
        user = self.request.user
        return models.ManuscriptItem.objects.filter(author=user)

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

    def perform_destroy(self, instance):
        instance.delete()

Destroy関数とdestroy関数の実行は、成功せずに試みたものです。これは私が試したときに返されるものです:

{"detail": "メソッド\" DELETE\"は許可されていません。" }

これが私のURLが現在登録されている方法です:

router = DefaultRouter()
router.register('manuscripts', views.ManuscriptViewSet, base_name="manuscripts")  # auto basename for models
router.register('manuscriptlibrary', views.ManuscriptLibraryViewSet, base_name="manuscript_library")
router.register('manuscriptsettings', views.ManuscriptSettingsViewSet)


urlpatterns = [
    url(r'', include(router.urls))
]

ModelViewSetの性質上、別の方法を使用する必要がありますか?許可されたユーザーを使用してManuscriptItemインスタンスを削除すると、Postmanで機能することが期待されました。ドキュメントでは、Destroy()メソッドを使用できると述べています。

追加情報

使用されるURLは次のとおりです。

http:// localhost:8000/manuscripts-api/manuscripts /

削除するモデルインスタンス:

class ManuscriptItem(models.Model):
    """Represents a single manuscript's content"""

    author = models.ForeignKey('accounts_api.UserProfile', on_delete=models.CASCADE)
    title = models.CharField(max_length=255)
    content = models.CharField(max_length=99999999)

    def __str__(self):
        """Django uses when it needs to convert the object to a string"""
        return str(self.id)

私がjsonでpostmanに削除リクエストを送信しようとした方法:

{
    "manuscript": 7,
}

結果:削除メソッドは許可されていません

{
    "id": 7,
    "author": 5,
    "title": "niceone",
    "content": "niceone"
}

結果:削除メソッドは許可されていません

追加の質問/情報:

ルーターレジスタをpkで指定する必要はありませんか?私はこれを試しましたが、どちらもうまくいきませんでした:

router.register('manuscripts/{pk}/$', views.ManuscriptViewSet, base_name="manuscript_detail")

郵便配達さんのコメント:

許可→GET、POST、HEAD、OPTIONS

7
NewScientists

ここでの問題は、DELETEリクエストを間違ったURLに送信することです。 DefaultRouter docs を見てください。 viewset内にURLを自動的に生成します:

DefaultRouter class url patterns

DELETEメソッドをよく見てください。 {prefix}/{lookup}/[.format] urlパターン上にあります。つまり、対応するルーターのURLはmanuscripts/<manuscript_id>/ですが、DELETEリクエストをmanuscripts/のみに送信しようとすると、上記のパターンになります。許可されているHTTPメソッドはGETPOSTのみであることが表から直接わかります。これがMethodNotAllowedを受け取る理由です。

問題の解決策は、manuscript_idをリクエストのJSONボディとして渡さないことです

{
    "manuscript": 7,
}

しかし、それを直接urlに渡すには:

DELETEhttp:// localhost:8000/manuscripts-api/manuscripts/7 /

そして、あなたはあなたのビューセットを次のように登録するだけです:

router.register(r'manuscripts', ManuscriptViewSet.as_view(), name='manuscripts')

ご覧のとおり、[〜#〜] drf [〜#〜]は自動的にURLを生成します。

12
wencakisa
def destroy(self, request, *args, **kwargs):
        try:
            instance = self.get_object()
            self.perform_destroy(instance)
        except Http404:
            pass
        return Response(status=status.HTTP_204_NO_CONTENT)

これを使うとうまくいきます

6
Exprator