python / expert
Snippet
Django REST Framework ViewSet mit Custom Actions und Permission Klassen
Dieses Snippet demonstriert Django REST Framework ViewSet Customisierung mit dynamischer Berechtigungsbehandlung und Custom Actions. Das ViewSet implementiert aktionsspezifische Berechtigungen wobei retrieve und list öffentlich sind, archive und stats Mitgliedschaft erfordern, während Destroy-Operationen Adminrechte benötigen. Custom Actions wie archive, stats und bulk_archive bieten ressourcenspezifische Endpoints mit proper Berechtigungsdurchsetzung.
snippet.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
from rest_framework import viewsets, permissions, statusfrom rest_framework.decorators import actionfrom rest_framework.response import Responsefrom rest_framework.views import APIViewfrom django.shortcuts import get_object_or_404from myapp.models import Project, Membershipfrom myapp.serializers import ProjectSerializer, ProjectStatsSerializerfrom myapp.permissions import IsProjectMember, IsProjectAdminclass ProjectViewSet(viewsets.ModelViewSet):queryset = Project.objects.all()serializer_class = ProjectSerializerpermission_classes = [permissions.IsAuthenticated]def get_permissions(self):if self.action in ['retrieve', 'list']:return [permissions.AllowAny()]elif self.action in ['destroy', 'partial_update']:return [IsProjectAdmin()]elif self.action in ['archive', 'stats']:return [IsProjectMember()]return [permissions.IsAuthenticated()]def get_queryset(self):user = self.request.userif self.action == 'list' and not self.request.user.is_authenticated:return Project.objects.filter(is_public=True)return super().get_queryset()@action(detail=True, methods=['post'], permission_classes=[IsProjectAdmin])def archive(self, request, pk=None):project = self.get_object()project.is_archived = Trueproject.save()return Response({'status': 'archived'}, status=status.HTTP_200_OK)@action(detail=True, methods=['get'], url_path='statistics')def stats(self, request, pk=None):project = self.get_object()data = {'members_count': project.membership_set.count(),'tasks_completed': project.tasks.filter(is_completed=True).count(),'total_tasks': project.tasks.count(),}serializer = ProjectStatsSerializer(data)return Response(serializer.data)@action(detail=False, methods=['post'])def bulk_archive(self, request):ids = request.data.get('project_ids', [])projects = Project.objects.filter(id__in=ids, created_by=request.user)updated = projects.update(is_archived=True)return Response({'archived_count': updated})
django
Erklärung
1
def get_permissions(self):
Überschreibe um aktionsspezifische Permission Classes zurückzugeben für granulare Zugriffskontrolle pro Endpoint
2
@action(detail=True, methods=['post'], permission_classes=[IsProjectAdmin])
Definiere Custom Action Decorator mit detail=True für instanzspezifische Endpoints und explizite Berechtigungsanforderung
3
@action(detail=False, methods=['post'])
Erstelle Collection-Level Action für Bulk-Operationen ohne spezifische Ressourceninstanz
4
IsProjectMember()
Verwende Custom Permission Class die Benutzermitgliedschaft im spezifischen Projekt prüft auf das zugegriffen wird
5
url_path='statistics'
Überschreibe URL Pfad für die Action um 'statistics' statt Methodennamen 'stats' zu verwenden