4 votes

Organisation des vues du framework rest de Django à l'aide de génériques

Je fais mes premiers pas dans django ici, en construisant une simple api crud où j'ai deux entités : device et property.

mon projet urls.py ressemble à ceci :

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')),
]

et mon application urls.py comme suit :

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()),
]

ce qui est quelque peu répétitif mais bon, le vrai problème est que mon fichier de vues est bien plus répétitif :

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

J'ai cherché des exemples sur le web et cela semble être une méthode valable (de plus, mon application fonctionne), mais y a-t-il un moyen d'améliorer ma façon de faire ? views.py pour obtenir le même résultat avec moins de code ?

4voto

Marcell Erasmus Points 773

Vous pouvez utiliser un ModelViewSet pour votre PropertySerializer et un pour votre DeviceSerializer

Le ModelViewSet fournit par défaut create , retrieve , update , partial_update , destroy y list actions.

Votre views se présentent comme suit :

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()

Vous enregistrerez ensuite vos vues auprès d'un routeur dans votre urls.py comme suit :

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

Notez que votre classe de sérialiseur devra également être une classe ModelSerializer :

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

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

Vous trouverez plus d'informations à ce sujet dans le docs sur le cadre de repos

1voto

Kamil Points 668

Vous devez utiliser ModelViewSet de rest_framework dans ce cas, par exemple pour les appareils, il s'agirait d'un ViewSet comme indiqué ci-dessous :

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

puis dans votre 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

La principale différence réside dans le fait que le même point d'arrivée est utilisé pour différentes opérations. Elles se distinguent par les méthodes HTTP, par exemple

  • GET /devices serait égal à votre DeviceList
  • GET /devices/<id> serait égal à votre DeviceDetail
  • POST /devices serait égal à votre DeviceCreate
  • PUT /devices/<id> serait égal à votre DeviceUpdate
  • DELETE /devices/<id> serait égal à votre DeviceDelete

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X