Reputation: 1766
Trying to filter objects in my view.py
to only show items (in my case Buckets) owned by Users.
I implemented the code below in my original Model [my model.py
code is at the bottom of post]
class PostObjects(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(status=Bucket.owner)
But I'm not sure if that is the correct procedure to list all items?
Here is the view.py
where I'm trying to filter data by User aka owner
. Users should ONLY be allowed to view their own items. (I will deal with permissions later)
class BucketList(generics.ListCreateAPIView):
queryset = Bucket.objects.all() #INSERT FILTER HERE
pass
Here is the model I'm referring too.
class Bucket(models.Model):
options = (
('personal', 'Personal'),
('social', 'Social'),
)
class PostObjects(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(status=Bucket.owner)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='buckets')
users = models.ManyToManyField(settings.AUTH_USER_MODEL)
category = models.CharField(max_length=30, choices=options)
name = models.CharField(max_length=35)
created = models.DateTimeField(default=timezone.now)
slug = models.SlugField(unique=True, blank=True)
stock_count = models.IntegerField(blank=True, null=True)
stock_list = ArrayField(models.CharField(max_length=6),size=10)
objects = models.Manager()
postobjects = PostObjects()
class Meta:
ordering = ('-created',)
def total_stocks_calc(self):
self.stock_count = Bucket.objects.aggregate(Sum('stock_list', distinct=True))
self.save()
def get_absolute_url(self):
return reverse("bucket:bucket-view", kwargs={"slug": self.slug})
def __str__(self):
return self.stock_list
To re-state my question, how can I filter objects owned by users in class BucketList
for their private view only?
UPDATE:
from django.db.models import Q
from rest_framework import generics
from bucket.models import Bucket
from .serializers import BucketSerializer
class OwnerOrUserFilterBackend(filters.BaseFilterBackend):
queryset = Bucket.postobjects.all() # wondering if you didnt write this for brevity reasons or because its not need due to the class?
def filter_queryset(self, request, queryset, view):
return queryset.filter(
Q(owner=request.user) | #do I not need to change one of the filters too request.owner?
Q(users=request.user)
)
class BucketList(generics.ListCreateAPIView):
model = Bucket
filter_backends = [OwnerOrUserFilterBackend]
Upvotes: 2
Views: 905
Reputation: 476493
You can override the get_queryset
method and filter with self.request.user
:
class BucketList(generics.ListCreateAPIView):
model = Bucket
def get_queryset(self, *args, **kwargs):
return super.get_queryset(*args, **kwargs).filter(
owner=self.request.user
)
For an API view, it probably is however better to define a filter, and then use this over all the API views where you want to apply this:
class IsOwnerFilterBackend(filters.BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
return queryset.filter(owner=request.user)
Then you can use this in your ListCreateAPIView
with:
class BucketList(generics.ListCreateAPIView):
model = Bucket
filter_backends = [IsOwnerFilterBackend]
The advantage of this is that if you have other views that require the same filtering, you only need to add the IsOwnerFilterBackend
as filter_backend
.
Another filter could include both the owner and the users
as people who can see the BucketList
:
from django.db.models import Q
class OwnerOrUserFilterBackend(filters.BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
return queryset.filter(
Q(owner=request.user) |
Q(users=request.user)
)
then we thus filter with this filter:
class BucketList(generics.ListCreateAPIView):
model = Bucket
filter_backends = [OwnerOrUserFilterBackend]
Upvotes: 3