Django Rest Framework使用泛型视图组织

时间:2018-08-22 08:27:02

标签: django django-rest-framework

在django中迈出第一步,构建一个简单的crud api,其中我有两个实体:device和property。

我的项目urls.py如下:

from django.contrib import admin
from django.urls import include, path
from devices.views import index

urlpatterns = [
    path('', index, name='index'),
    path('admin/', admin.site.urls),
    path('api/', include('devices.urls')),
]

和我的应用urls.py如下:

from django.urls import path
from . import views

urlpatterns = [
    path('device/create/', views.DeviceCreate.as_view()),
    path('device/update/<int:pk>/', views.DeviceUpdate.as_view()),
    path('device/delete/<int:pk>/', views.DeviceDelete.as_view()),
    path('device/', views.DeviceList.as_view()),
    path('device/<int:pk>/', views.DeviceDetail.as_view()),

    path('property/create/', views.PropertyCreate.as_view()),
    path('property/update/<int:pk>/', views.PropertyUpdate.as_view()),
    path('property/delete/<int:pk>/', views.PropertyDelete.as_view()),
    path('property/', views.PropertyList.as_view()),
    path('property/<int:pk>/', views.PropertyDetail.as_view()),
]

这有点重复,但是可以,真正的问题是我的视图文件重复得多:

from rest_framework import generics

from .models import Device, Property
from .serializers import DeviceSerializer, PropertySerializer

from django.shortcuts import render

def index(request):
    return render(request, 'index.html')

class DeviceCreate(generics.CreateAPIView):
    queryset = Device.objects.all()
    serializer_class = DeviceSerializer

class DeviceList(generics.ListAPIView):
    queryset = Device.objects.all()
    serializer_class = DeviceSerializer

class DeviceUpdate(generics.UpdateAPIView):
    queryset = Device.objects.all()
    serializer_class = DeviceSerializer

class DeviceDelete(generics.DestroyAPIView):
    queryset = Device.objects.all()
    serializer_class = DeviceSerializer

class DeviceDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Device.objects.all()
    serializer_class = DeviceSerializer

class PropertyCreate(generics.CreateAPIView):
    queryset = Property.objects.all()
    serializer_class = PropertySerializer

class PropertyList(generics.ListAPIView):
    queryset = Property.objects.all()
    serializer_class = PropertySerializer

class PropertyUpdate(generics.UpdateAPIView):
    queryset = Property.objects.all()
    serializer_class = PropertySerializer

class PropertyDelete(generics.DestroyAPIView):
    queryset = Property.objects.all()
    serializer_class = PropertySerializer

class PropertyDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Property.objects.all()
    serializer_class = PropertySerializer

例如,我查看了网络,这似乎是一种有效的方法(加上我的应用程序正在运行),但是有没有一种方法可以改善我的views.py文件以更少的代码获得相同的结果?

2 个答案:

答案 0 :(得分:1)

在这种情况下,您应该在rest_framework中使用ModelViewSet,例如对于设备,它将是一个ViewSet,如下所示:

class DeviceViewSet(viewsets.ModelViewSet):
    queryset = Device.objects.all()
    serializer_class = DeviceSerializer

然后在您的urls.py

from myapp.views import DeviceViewSet
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r'device', DeviceViewSet, base_name='device')
urlpatterns = router.urls

主要区别在于,对于不同的操作,您具有相同的端点。它们通过HTTP方法来区分,例如。

  • 获取/devices等于您的DeviceList
  • 获取/devices/<id>等于您的DeviceDetail
  • POST /devices等于您的DeviceCreate
  • 输入/devices/<id>等于您的DeviceUpdate
  • 删除/devices/<id>等于您的DeviceDelete

答案 1 :(得分:1)

您可以为ModelViewSet使用一个PropertySerializer,为DeviceSerializer使用一个

ModelViewSet提供默认的createretrieveupdatepartial_updatedestroylist操作。

您的views看起来像这样:

class DeviceViewSet(ModelViewSet):
    serializer_class = DeviceSerializer

    def get_queryset(self):
        return Device.objects.all()


class PropertyViewSet(ModelViewSet):
    serializer_class = PropertySerializer

    def get_queryset(self):
        return Property.objects.all()

然后您将在urls.py中的路由器上注册视图,如下所示:

from . import views
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r'devices', views.DeviceViewSet, base_name='device')
router.register(r'properties', views.PropertyViewSet, base_name='property')
urlpatterns = router.urls

请注意,您的序列化器类也必须是ModelSerializer

class DeviceSerializer(ModelSerializer):
    class Meta:
        model = Device
        fields = ('foo', 'bar')


class PropertySerializer(ModelSerializer):
    class Meta:
        model = Device
        fields = ('foo', 'bar')

您可以在rest framework docs

中了解更多信息