我在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())
]
这可以按预期工作。但是,很明显,由于URI中也带有http方法,因此这些API端点的设计不佳。 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可以帮助实现这一点,但是由于某些其他限制,我不能使用它们。仅使用我正在使用的基于类的视图就可以实现吗?
答案 0 :(得分:0)
很惊讶这个人没有收到答复。
这与 HTTP 动词以及 Django Rest Framework 如何映射它们有关。
无论如何,你会优先为你的视图集想要类似的东西:
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/<uuid:uuid>
或 http://example.com/api/v1/trips/<id:id>
,本质上与上面相同,但有一个额外的空间用于传入一些主键,因此服务器知道哪个对象你的目标是。同样,每个操作都根据您使用的 HTTP 动词操作进行区分,因此对于检索、更新和销毁,您需要将 get、put 或 delete 动词传递给请求端点。
希望这是有道理的!