【问题标题】:RestFul API endpoints with Django Rest Framework Class based views具有基于 Django Rest Framework 类的视图的 RestFul API 端点
【发布时间】:2019-04-22 19:02:22
【问题描述】:

我在 DRF 中有以下 4 个基于类的视图,用于对名为 Trips 的模型执行 CRUD 操作。

from rest_framework import generics

class TripCreateView(CreateAPIView): 
    #code that creates a Trip

class TripListView(ListAPIView):
    #code that lists Trips

class TripDetailView(RetrieveAPIView):
    #code that gives details of a Trip

class TripUpdateView(UpdateAPIView):
    #code that updates a particular trip details

class TripDeleteView(DestroyAPIView):
    #code that deletes an instance

现在为了将 url 连接到每个视图,我的 urls.py 看起来像这样:

urlpatterns = [
url(r'^trip/$', TripCreateView.as_view()),
url(r'^trip/list/$',TripListView.as_view()),
url(r'^trip/(?P<pk>[0-9]+)/detail/$', TripDetailView.as_view()),
url(r'^trip/(?P<pk>[0-9]+)/update/$', TripUpdateView.as_view()),
url(r'^trip/(?P<pk>[0-9]+)/delete/$', TripDeleteView.as_view())
]

这按预期工作。但是,很明显,这些 API 端点设计不佳,因为 URI 中也包含 http 方法。 RESTFUL API 端点在 URI 中没有 HTTP 方法,如下所示:

Endpoint             HTTP METHOD          Result
trips                GET                Gets all Trips
trips/:id            GET                Gets details of a Trip
trips                POST               Creates a Trip
trips/:id            PUT                Updates a Trip
trips:/id            DELETE             Deletes a Trip

我知道 Viewsets 可以帮助实现这一点,但由于某些其他限制,我无法使用它们。这可以通过使用我正在使用的基于类的视图来实现吗?

【问题讨论】:

  • 但这正是视图集的用途。什么“其他限制”?
  • @Daniel Roseman..如何在视图集中为不同的方法(如列表、创建等)使用不同的权限类?
  • 您可以创建一个custom permissions class,或者您可以在您的子类中定义这些方法并在调用超级方法之前检查权限。

标签: python django django-rest-framework django-urls django-rest-viewsets


【解决方案1】:

很惊讶这个没有收到答案。

这与 HTTP 动词以及 Django Rest 框架如何映射它们有关。

无论如何,你会优先考虑像你的视图集这样的东西:

from rest_framework import (
    mixins,
    viewsets
)

from trips.models import Trip
from trips.api.serializers import TripSerializer

class TripView(
    viewsets.GenericViewSet,
    mixins.ListModelMixin,
    mixins.CreateModelMixin,
    mixins.RetrieveModelMixin,
    mixins.UpdateModelMixin,
    mixins.DestroyModelMixin,
):

    queryset = Trip.objects.all()
    serializer_class = TripSerializer

    """
    Example empty viewset demonstrating the standard
    actions that will be handled by a router class.

    If you're using format suffixes, make sure to also include
    the `format=None` keyword argument for each action.
    """

    def list(self, request):
        pass

    def create(self, request):
        pass

    def retrieve(self, request, pk=None):
        pass

    def update(self, request, pk=None):
        pass

    def destroy(self, request, pk=None):
        pass

更多信息在这里:https://www.django-rest-framework.org/api-guide/viewsets/

如果做不到这一点,你可以修改这些代码行:

urlpatterns = [
    url(r'^trips/$',TripListView.as_view({'get': 'list'})),
    url(r'^trips/$', TripCreateView.as_view({'post': 'create'})),
    url(r'^trips/(?P<pk>[0-9]+)/$', TripDetailView.as_view({'get': 'retrieve'})),
    url(r'^trips/(?P<pk>[0-9]+)/$', TripUpdateView.as_view({'put': 'update'})),
    url(r'^trips/(?P<pk>[0-9]+)/$', TripDeleteView.as_view({'delete': 'destroy'}))
]

也就是说,您有一个基本端点http://example.com/api/v1/trips,然后每个操作都不是通过将其附加到 url 而是通过您正在使用的 http 动词来映射的。最佳实践是在基本端点上有一个 get 和一个 post,一个“列表”,另一个将“创建”(要创建,您必须将一个完全 JSON 序列化的对象发布到创建端点)。因此,使用这两个动词,您可以使用相同的端点,但用于不同的资源操作。

检索、更新和销毁端点也是如此。这些操作的端点是相同的:类似于http://example.com/api/v1/trips/&lt;uuid:uuid&gt; 或http://example.com/api/v1/trips/&lt;id:id&gt;,本质上与上面相同,但有一个额外的空间用于传递一些主键,因此服务器知道您的目标是哪个对象为了。同样,每个动作都由您使用的 HTTP 动词动作区分,因此对于检索、更新和销毁,您需要将 get、put 或 delete 动词传递给请求端点。

希望这是有道理的!

【讨论】:

    猜你喜欢
    • 2018-04-29
    • 1970-01-01
    • 1970-01-01
    • 2018-12-11
    • 2015-11-24
    • 2020-03-02
    • 2023-03-08
    • 1970-01-01
    • 2018-11-19
    相关资源
    最近更新 更多