python / expert
Snippet
Django Generic Views mit Dynamischer Queryset-Filterung und Permission Matrix
Generic Views kombiniert mit Permission Matrices ermöglichen Fine-Grained Access Control ohne repetitive Decorator-Logik. Die cached_property permission_matrix cached Berechtigungsprüfungen pro Request und vermeidet wiederholte Datenbankabfragen. Dynamische Queryset-Filterung via GET-Parametern ermöglicht JavaScript-freie gefilterte Views, während Query-Effizienz durch select_related gewahrt wird.
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
from django.views.generic import ListView, DetailViewfrom django.core.exceptions import PermissionDeniedfrom django.contrib.auth.mixins import LoginRequiredMixinfrom functools import cached_propertyclass ArticleDetailView(LoginRequiredMixin, DetailView):model = Articlecontext_object_name = 'article'template_name = 'articles/detail.html'def get_queryset(self):user = self.request.userif user.is_superuser:return Article.objects.all()if user.has_perm('articles.view_article'):return Article.objects.filter(status='published')return Article.objects.none()def get_object(self):obj = super().get_object()if not self.request.user.has_perm('articles.view_detail', obj):raise PermissionDenied('Access denied to unpublished details')return objclass ArticleListView(ListView):model = Articlecontext_object_name = 'articles'paginate_by = 20@cached_propertydef permission_matrix(self):return {'can_publish': self.request.user.has_perm('articles.publish'),'can_archive': self.request.user.has_perm('articles.archive'),'can_edit': self.request.user.has_perm('articles.change'),}def get_queryset(self):queryset = Article.objects.select_related('author')status = self.request.GET.get('status')if status in ['published', 'draft', 'archived']:queryset = queryset.filter(status=status)author = self.request.GET.get('author')if author:queryset = queryset.filter(author__username=author)return querysetdef get_context_data(self, **kwargs):context = super().get_context_data(**kwargs)context['permissions'] = self.permission_matrixreturn context
django
Erklärung
1
@cached_property
def permission_matrix(self):
Cacht Berechtigungsprüfungen für gesamten Request-Lebenszyklus
2
if user.is_superuser: return Article.objects.all()
Superuser umgehen Filterung und sehen alle Artikel
3
if not self.request.user.has_perm('articles.view_detail', obj):
Objekt-Level Berechtigungsprüfung mit dynamischem obj Parameter
4
status = self.request.GET.get('status')
if status in [...]:
Dynamische Queryset-Filterung aus URL Query-Parametern
5
context_object_name = 'articles'
Context-Variablen Namenskonvention für Template-Klarheit