Leer hoe je jouw Django REST Framework API's effectief organiseert met ViewSets. Deze gids behandelt alles van basisgebruik tot geavanceerde aanpassingen.
Django REST Framework ViewSets: API Endpoint Organisatie Onder de Knie Krijgen
In moderne web development is het bouwen van robuuste en goed gestructureerde API's cruciaal. Django REST Framework (DRF) is een krachtige toolkit voor het creƫren van RESTful API's met Django. Hoewel DRF verschillende tools biedt voor het creƫren van API endpoints, bieden ViewSets een elegante manier om gerelateerde views te organiseren in een enkele klasse, wat leidt tot schonere en beter onderhoudbare code. Deze uitgebreide gids zal ViewSets in detail verkennen, waarbij hun voordelen, gebruik en geavanceerde aanpassingstechnieken worden behandeld.
Wat zijn ViewSets?
Een ViewSet is een op klassen gebaseerde View die implementaties biedt voor standaard bewerkingen, zoals list
, create
, retrieve
, update
en destroy
. In plaats van afzonderlijke views te definiƫren voor elke bewerking, combineert een ViewSet ze in een enkele klasse, waardoor de API structuur wordt vereenvoudigd en codeduplicatie wordt verminderd. ViewSets zijn vooral handig bij het werken met model-gebaseerde API's, waar deze standaard bewerkingen vaak vereist zijn. Beschouw een ViewSet als een logische groepering van bewerkingen op een specifieke resource.
Voordelen van het Gebruiken van ViewSets
- Code Herbruikbaarheid: ViewSets bevorderen code hergebruik door gemeenschappelijke API logica in een enkele klasse in te kapselen. Dit vermindert redundantie en maakt de code gemakkelijker te onderhouden.
- Vereenvoudigde Routing: ViewSets vereenvoudigen routing door gerelateerde views te groeperen onder een enkel URL prefix. Dit resulteert in een schonere en beter georganiseerde URL structuur.
- Verminderde Boilerplate: ViewSets verminderen boilerplate code door standaard implementaties te bieden voor veelvoorkomende API bewerkingen. Hierdoor kunnen ontwikkelaars zich richten op het implementeren van aangepaste logica die specifiek is voor hun applicatie.
- Verbeterde Leesbaarheid: ViewSets verbeteren de leesbaarheid van de code door gerelateerde views te organiseren in een enkele klasse. Dit maakt de API structuur gemakkelijker te begrijpen en te navigeren.
- Consistentie: ViewSets helpen de consistentie in de API te waarborgen door een standaard set van bewerkingen en conventies af te dwingen. Dit maakt de API voorspelbaarder en gemakkelijker te gebruiken.
Basis Gebruik van ViewSets
Laten we beginnen met een eenvoudig voorbeeld van het gebruik van ViewSets om een API te maken voor het beheren van producten. Definieer eerst een model:
# models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=255)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
def __str__(self):
return self.name
Definieer vervolgens een serializer voor het Product
model:
# serializers.py
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
Maak nu een ViewSet voor het Product
model:
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
Configureer ten slotte de URL routing:
# urls.py
from django.urls import path, include
from rest_framework import routers
from . import views
router = routers.DefaultRouter()
router.register(r'products', views.ProductViewSet)
urlpatterns = [
path('', include(router.urls)),
]
Deze configuratie genereert automatisch de volgende API endpoints:
/products/
(GET: list, POST: create)/products/{id}/
(GET: retrieve, PUT: update, PATCH: partial_update, DELETE: destroy)
De ModelViewSet
biedt standaard implementaties voor alle standaard CRUD bewerkingen. Het queryset
attribuut specificeert de set objecten waarop de ViewSet moet opereren, en het serializer_class
attribuut specificeert de serializer die moet worden gebruikt voor het serialiseren en deserialiseren van data.
Types van ViewSets
DRF biedt verschillende ingebouwde ViewSet klassen die inspelen op verschillende use cases:
ViewSet
: De basisklasse voor alle ViewSets. Het biedt de basisinfrastructuur voor het afhandelen van requests en responses.ReadOnlyModelViewSet
: Een ViewSet die alleen-lezen bewerkingen biedt (list
enretrieve
). Dit is handig voor API's die alleen data ophalen toestaan.ModelViewSet
: Een ViewSet die alle standaard CRUD bewerkingen biedt (list
,create
,retrieve
,update
endestroy
). Dit is de meest gebruikte ViewSet voor model-gebaseerde API's.GenericViewSet
: Een ViewSet die een generieke implementatie biedt voor veelvoorkomende API bewerkingen. Dit kan worden gebruikt als een basisklasse voor het maken van aangepaste ViewSets.
Het kiezen van de juiste ViewSet hangt af van de specifieke vereisten van uw API. Als u alleen alleen-lezen bewerkingen nodig hebt, gebruik dan ReadOnlyModelViewSet
. Als u alle standaard CRUD bewerkingen nodig hebt, gebruik dan ModelViewSet
. Als u meer controle nodig hebt over het API gedrag, kunt u een aangepaste ViewSet maken door te erven van GenericViewSet
of ViewSet
.
ViewSets Aanpassen
Hoewel de ingebouwde ViewSets een handige manier bieden om API's te maken, kan het nodig zijn om hun gedrag aan te passen om aan specifieke eisen te voldoen. DRF biedt verschillende manieren om ViewSets aan te passen, waaronder het overschrijven van methoden, het toevoegen van aangepaste acties en het gebruik van aangepaste serializers.
Methoden Overschrijven
U kunt de standaard implementaties van de standaard API bewerkingen overschrijven door methoden met dezelfde namen te definiƫren in uw ViewSet klasse. U kunt bijvoorbeeld de create
methode overschrijven om aangepaste logica toe te voegen voor of na het aanmaken van een nieuw object:
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from rest_framework.response import Response
from rest_framework import status
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
# Add custom logic here before creating the object
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
In dit voorbeeld overschrijft de create
methode de standaard implementatie en voegt aangepaste logica toe voordat het object wordt aangemaakt. De perform_create
methode wordt aangeroepen om het object daadwerkelijk aan te maken, en de response wordt geretourneerd met een 201 Created
status code.
Aangepaste Acties Toevoegen
U kunt aangepaste acties toevoegen aan uw ViewSet met behulp van de @action
decorator. Met aangepaste acties kunt u nieuwe API endpoints definiƫren die specifieke bewerkingen uitvoeren op de resources die door de ViewSet worden beheerd. U kunt bijvoorbeeld een actie toevoegen om een product als uitgelicht te markeren:
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import status
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
@action(detail=True, methods=['post'])
def feature(self, request, pk=None):
product = self.get_object()
product.is_featured = True
product.save()
serializer = self.get_serializer(product)
return Response(serializer.data)
In dit voorbeeld definieert de @action
decorator een nieuw API endpoint /products/{id}/feature/
dat een product als uitgelicht markeert. Het detail=True
argument geeft aan dat de actie op een specifieke instantie van het model werkt. Het methods=['post']
argument specificeert dat de actie alleen POST requests accepteert.
Aangepaste Serializers Gebruiken
U kunt aangepaste serializers gebruiken om de manier aan te passen waarop data wordt geserialiseerd en gedeserialiseerd door de ViewSet. Dit is handig wanneer u complexe datastructuren moet verwerken of aangepaste validatie moet uitvoeren. U kunt bijvoorbeeld een aangepaste serializer gebruiken om gerelateerde data op te nemen in de API response:
# serializers.py
from rest_framework import serializers
from .models import Product, Category
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ['id', 'name']
class ProductSerializer(serializers.ModelSerializer):
category = CategorySerializer(read_only=True)
class Meta:
model = Product
fields = '__all__'
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
In dit voorbeeld bevat de ProductSerializer
een CategorySerializer
om de gerelateerde categorie data te serialiseren. Hierdoor kunt u de categorie informatie samen met de product informatie ophalen in een enkel API request.
Geavanceerde ViewSet Technieken
Naast basisgebruik en aanpassing bieden ViewSets geavanceerde technieken voor het bouwen van geavanceerde API's:
Filteren
DRF biedt krachtige filtermogelijkheden waarmee u de queryset kunt filteren op basis van request parameters. U kunt het filter_backends
attribuut gebruiken om de te gebruiken filter backends te specificeren. U kunt bijvoorbeeld de SearchFilter
gebruiken om gebruikers in staat te stellen producten te zoeken op naam of beschrijving:
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from rest_framework import filters
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [filters.SearchFilter]
search_fields = ['name', 'description']
In dit voorbeeld specificeert het filter_backends
attribuut dat de SearchFilter
moet worden gebruikt. Het search_fields
attribuut specificeert de velden die moeten worden doorzocht.
Paginering
DRF biedt pagineringsmogelijkheden waarmee u de queryset in kleinere pagina's kunt verdelen. Dit is handig bij het omgaan met grote datasets. U kunt het pagination_class
attribuut gebruiken om de te gebruiken pagineringsklasse te specificeren. U kunt bijvoorbeeld de PageNumberPagination
gebruiken om de resultaten te pagineren met behulp van paginanummers:
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from rest_framework.pagination import PageNumberPagination
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
pagination_class = PageNumberPagination
In dit voorbeeld specificeert het pagination_class
attribuut dat de PageNumberPagination
moet worden gebruikt. U kunt het pagineringsgedrag ook aanpassen door uw eigen pagineringsklasse te maken.
Authenticatie en Permissies
DRF biedt flexibele authenticatie- en permissiemechanismen waarmee u de toegang tot uw API endpoints kunt beheren. U kunt de authentication_classes
en permission_classes
attributen gebruiken om de te gebruiken authenticatie- en permissieklassen te specificeren. U kunt bijvoorbeeld de TokenAuthentication
gebruiken om gebruikers te authenticeren met behulp van tokens en de IsAuthenticated
permissie om alleen geauthenticeerde gebruikers toegang te geven tot de API:
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
In dit voorbeeld specificeert het authentication_classes
attribuut dat de TokenAuthentication
moet worden gebruikt, en het permission_classes
attribuut specificeert dat de IsAuthenticated
permissie moet worden gebruikt.
Best Practices voor het Gebruiken van ViewSets
Om ervoor te zorgen dat uw ViewSets goed ontworpen en onderhoudbaar zijn, volgt u deze best practices:
- Houd ViewSets gefocust: Elke ViewSet moet verantwoordelijk zijn voor het beheren van een enkele resource of een nauw verwante set van resources. Vermijd het maken van overdreven complexe ViewSets die meerdere niet-gerelateerde bewerkingen afhandelen.
- Gebruik de juiste ViewSet types: Kies het ViewSet type dat het beste past bij de vereisten van uw API. Gebruik
ReadOnlyModelViewSet
voor alleen-lezen API's,ModelViewSet
voor CRUD API's enGenericViewSet
ofViewSet
voor aangepaste API's. - Volg RESTful principes: Ontwerp uw API endpoints volgens RESTful principes. Gebruik standaard HTTP methoden (GET, POST, PUT, PATCH, DELETE) om bewerkingen uit te voeren op resources.
- Gebruik serializers voor data validatie: Gebruik serializers om de data te valideren die naar en van de API wordt verzonden en ontvangen. Dit helpt de data integriteit te waarborgen en fouten te voorkomen.
- Implementeer de juiste authenticatie en permissies: Beveilig uw API endpoints door de juiste authenticatie en permissies te implementeren. Dit helpt uw data te beschermen tegen ongeautoriseerde toegang.
- Schrijf uitgebreide tests: Schrijf uitgebreide tests om ervoor te zorgen dat uw ViewSets correct werken. Dit helpt regressies te voorkomen en maakt het gemakkelijker om de code te onderhouden.
Internationalisatie (i18n) en Lokalisatie (l10n) Overwegingen
Bij het bouwen van API's voor een wereldwijd publiek is het essentieel om rekening te houden met internationalisatie (i18n) en lokalisatie (l10n). ViewSets kunnen worden aangepast om meerdere talen en regio's te ondersteunen:
- Serializer Velden: Gebruik DRF's serializer velden met de juiste vertaalfuncties (bijv.
gettext
van Django's i18n framework) om vertaalde veldlabels en helpteksten weer te geven. - Foutmeldingen: Zorg ervoor dat foutmeldingen die door de API worden geretourneerd, worden vertaald in de voorkeurstaal van de gebruiker.
- Datum- en Tijdnotatie: Gebruik de juiste datum- en tijdnotatie op basis van de locale van de gebruiker. DRF biedt opties voor het aanpassen van datum- en tijdnotaties.
- Valuta Notatie: Formatteer valutawaarden volgens de locale van de gebruiker. Overweeg het gebruik van bibliotheken zoals
babel
voor valuta notatie. Een prijs van 1234,56 USD kan bijvoorbeeld worden geformatteerd als $1.234,56 in de VS, maar als 1.234,56 $ in sommige Europese landen. - Tijdzones: Behandel tijdzones correct. Sla datums en tijden op in UTC en converteer ze naar de lokale tijdzone van de gebruiker bij het weergeven ervan.
Een product kan bijvoorbeeld een beschrijving hebben die moet worden vertaald. U zou Django's vertaalsysteem binnen de serializer gebruiken:
# serializers.py
from rest_framework import serializers
from django.utils.translation import gettext_lazy as _
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
description = serializers.CharField(help_text=_("Product description"))
class Meta:
model = Product
fields = '__all__'
En zorg er in uw templates of code die deze serializer gebruikt voor dat de juiste taal is geactiveerd.
Voorbeeld: E-commerce API met Internationale Ondersteuning
Stel je een e-commerce API voor die producten wereldwijd verkoopt. Het Product
model kan velden bevatten zoals name
, description
, price
en image
. De API moet meerdere talen en valuta's ondersteunen.
De ViewSet zou de basis CRUD bewerkingen voor producten afhandelen. De serializers zouden worden aangepast om vertaling van de productnaam en beschrijving te ondersteunen. De API zou ook endpoints bevatten voor het ophalen van producten per categorie, het filteren van producten op prijsklasse en het zoeken naar producten op trefwoord. Deze functies zouden rekening moeten houden met internationalisatie, met name rond zoektermen en productbeschrijvingen die per taal kunnen verschillen.
Voorbeeld URLS:
/en/products/
- Lijst van producten in het Engels/fr/products/
- Lijst van producten in het Frans/en/products/?currency=USD
- Lijst van producten in USD/fr/products/123/?currency=EUR
- Details van product 123 in het Frans, prijs weergegeven in EUR
Conclusie
Django REST Framework ViewSets bieden een krachtige en elegante manier om uw API endpoints te organiseren. Door gerelateerde views in een enkele klasse in te kapselen, bevorderen ViewSets code hergebruik, vereenvoudigen ze routing en verbeteren ze de leesbaarheid van de code. Met de mogelijkheid om ViewSets aan te passen door methoden te overschrijven, aangepaste acties toe te voegen en aangepaste serializers te gebruiken, kunt u ze afstemmen op de specifieke vereisten van uw API. Door de best practices te volgen die in deze handleiding worden beschreven, kunt u ervoor zorgen dat uw ViewSets goed ontworpen, onderhoudbaar en schaalbaar zijn, wat resulteert in robuuste en efficiƫnte API's.
Vergeet niet om rekening te houden met internationalisatie en lokalisatie bij het bouwen van API's voor een wereldwijd publiek. Pas uw ViewSets en serializers aan om meerdere talen, valuta's en tijdzones te ondersteunen om een naadloze ervaring te bieden aan gebruikers over de hele wereld.
Door ViewSets onder de knie te krijgen, kunt u uw Django REST Framework vaardigheden naar een hoger niveau tillen en API's bouwen die zowel krachtig als onderhoudbaar zijn. Dit draagt bij aan software van hoge kwaliteit en een positieve gebruikerservaring voor uw wereldwijde publiek.
Deze gids zou moeten dienen als een solide basis voor het begrijpen en implementeren van ViewSets in uw Django REST Framework projecten. Blijf oefenen, experimenteren en de DRF documentatie verkennen om een echte ViewSet meester te worden!