如何在 Django REST Framework 中使用相同的确切路径将不同的请求类型映射到不同的视图?

How to map different request types to different views using the same exact path in Django REST Framework?

我想要一个 url 类似 api/instrument/{id} 的东西,然后根据请求类型 GET, POST, DELETE 将请求路由到我的 Django 应用程序中的不同视图。

我有以下看法:

from django.shortcuts import render
from django.http.response import JsonResponse, 
from django.http.request import HttpRequest
from rest_framework.parsers import JSONParser
from rest_framework import status
from Instruments.services import instruments_service
from models import Instrument
from serializers import InstrumentsSerializer
from rest_framework.decorators import api_view
from services import InstrumentsService

# Application views live here
@api_view('GET')
def get_instrument_by_id(request:HttpRequest, id):
    instrument_service = InstrumentsService()
 
    data={}
    try:    
        data = instrument_service.get_instrument_by_id(id)
        return JsonResponse(data,status=status.HTTP_200_OK, safe=False)
    except Exception as exc:
        return JsonResponse({"Status":f"Error: {exc}"},status=status.HTTP_404_NOT_FOUND , safe=False)


@api_view('POST')
def update_instrument_by_id(request:HttpRequest, id):
    instrument_service = InstrumentsService()
    instrument_data = JSONParser().parse(request)
    
 
    data={}
    try:    
        data = instrument_service.update_instrument_by_id(id, instrument_data)
        return JsonResponse(data,status=status.HTTP_200_OK, safe=False)
    except Exception as exc:
        return JsonResponse({"Status":f"Error: {exc}"},status=status.HTTP_404_NOT_FOUND , safe=False)


@api_view('DELETE')
def delete_instrument_by_id(request:HttpRequest, id):
    instrument_service = InstrumentsService()
 
    data={}
    try:    
        data = instrument_service.delete_instrument_by_id(id)
        return JsonResponse(data,status=status.HTTP_200_OK, safe=False)
    except Exception as exc:
        return JsonResponse({"Status":f"Error: {exc}"},status=status.HTTP_404_NOT_FOUND , safe=False)

我看到人们使用 django 制作一个函数来处理所有请求,然后他们在里面有 logioc 但这对我来说似乎是错误的。有没有办法根据请求类型将相同的 URL 端点映射到不同的函数?

例如,我在这里看到每个 url 都映射到一个视图,但未在任何地方指定请求类型 URL_Dispatcher

好的,基于 Django REST 框架提供的基于 class 的视图,并在原始 post 的评论中使用,我制作了这个 class 自动处理所有请求类型在同一端点的类型上:

from uuid import UUID
from django.shortcuts import render
from django.http.response import JsonResponse
from django.http.request import HttpRequest
from rest_framework import viewsets, status
from rest_framework.parsers import JSONParser
from rest_framework.response import Response
from Instruments.services import InstrumentsService
from rest_framework.decorators import api_view
from Instruments.services import InstrumentsService
from injector import singleton, inject


# Application views live here
@singleton
class InstrumentViewSet(viewsets.ModelViewSet):
    @inject
    def __init__(self, instrument_service: InstrumentsService, **kwargs):
        self.instrument_service = instrument_service
        super().__init__(**kwargs)

    def list(self, request: HttpRequest):
        data = {}

        try:
            data = self.instrument_service.get_instruments()
            return JsonResponse(data, status=status.HTTP_200_OK, safe=False)
        except Exception as exc:
            return JsonResponse(
                {"Status": f"Error: {exc}"},
                status=status.HTTP_400_BAD_REQUEST,
                safe=False,
            )

    def create(self, request):
        instrument_data = JSONParser().parse(request)
        data = {}

        try:
            data = self.instrument_service.add_instrument(instrument_data)
            return JsonResponse(data, status=status.HTTP_201_CREATED, safe=False)
        except Exception as exc:
            return JsonResponse(data, status=status.HTTP_400_BAD_REQUEST, safe=False)

    def retrieve(self, request, pk: UUID = None):
        data = {}

        try:
            data = self.instrument_service.get_instrument_by_id(pk)
            return JsonResponse(data, status=status.HTTP_200_OK, safe=False)
        except Exception as exc:
            return JsonResponse(
                {"Status": f"Error: {exc}"},
                status=status.HTTP_404_NOT_FOUND,
                safe=False,
            )

    def update(self, request, pk: UUID = None):
        instrument_data = JSONParser().parse(request)
        data = {}

        try:
            data = self.instrument_service.update_instrument_by_id(pk, instrument_data)
            return JsonResponse(data, status=status.HTTP_200_OK, safe=False)
        except Exception as exc:
            return JsonResponse(
                {"Status": f"Error: {exc}"},
                status=status.HTTP_404_NOT_FOUND,
                safe=False,
            )

    def destroy(self, request, pk: UUID = None):
        data = {}
        try:
            data = self.instrument_service.delete_instrument_by_id(pk)
            return JsonResponse(data, status=status.HTTP_200_OK, safe=False)
        except Exception as exc:
            return JsonResponse(
                {"Status": f"Error: {exc}"},
                status=status.HTTP_404_NOT_FOUND,
                safe=False,
            )