Reputation: 333
I am creating an api with Django rest framework. I use only ModelViewsSet. I need the result of some viewset to be different depending on the user who makes the request.
For the moment I have overloaded the get_query_set method for each ModelViewSet. This works very well, depending on the user the results are different for the "list" and also for the "read" which returns a 404 if the user tries to access an element he doesn't have the right to.
def get_queryset(self):
if self.request.user.is_staff:
return cache.get_or_set(
'machine_machines_list',
Machine.objects.all() \
.select_related('category') \
.prefetch_related('machine_stock') \
.prefetch_related('components'),
60)
else:
return cache.get_or_set(
f'machine_machines_list_user_{self.request.user.pk}',
Machine.objects.filter(site__user=self.request.user)\
.select_related('category') \
.prefetch_related('machine_stock') \
.prefetch_related('components'),
60)
However I'm not sure if this is the best method or if it is really secure. Is it the right method? Or is there a better way to do it?
Upvotes: 1
Views: 553
Reputation: 4034
That's a good option. Actually, that's basically the only option to limit the list response, and also giving you "for free" checks for the read/update/delete. I would recommend to clean-up it a bit though to reduce duplication and improve clarity:
def get_queryset(self):
queryset = Machine.objects\
.select_related('category') \
.prefetch_related('machine_stock', 'components')
user = self.request.user
if user.is_staff:
cache_key = 'machine_machines_list'
else:
queryset = queryset.filter(site__user=user)
cache_key = f'machine_machines_list_user_{user.pk}'
return cache.get_or_set(cache_key, queryset, 60)
Upvotes: 2