taha maatof
taha maatof

Reputation: 2165

filter access to detailview by a simple field and/or a manytomanyfield

I want to limit the access to detailView of a chatroom to the owner and participants of the room(joiners)

model:

class PublicChatRoom(models.Model): 
    title = models.CharField(max_length=100, unique=True, blank=False)
    owner = models.ForeignKey(User,related_name='chatrooms_created',on_delete=models.CASCADE)
    joiners = models.ManyToManyField(User, blank=True,related_name='chatrooms_joined')

view:

class JoinerRoomDetailView(DetailView):
    model = PublicChatRoom
    template_name = 'detail.html'

    def get_queryset(self):
        return PublicChatRoom.objects.filter(Q(joiners__in=[self.request.user]) | Q(owner=self.request.user))  

and some rooms give the following error :

get() returned more than one PublicChatRoom -- it returned 2!

if I use the view like this:

class JoinerRoomDetailView(DetailView):
    model = PublicChatRoom
    template_name = 'detail.html'

    def get_queryset(self):
        return PublicChatRoom.objects.filter(Q(joiners__in=[self.request.user])) #the modified part

only if the user that is in participant list have access, which is correct

and if it's that:

class JoinerRoomDetailView(DetailView):
    model = PublicChatRoom
    template_name = 'detail.html'

    def get_queryset(self):
        return PublicChatRoom.objects.filter(Q(owner=self.request.user))  #the modified part

only the creator of room can see it, again correct everything works as expected.

but the Goal is to access rooms that a user own or a part of both, so how can I do that?

Upvotes: 0

Views: 34

Answers (1)

Trent
Trent

Reputation: 3103

Because you have an "OR" clause that will both return a record, you need to make sure you return "distinct" records

class JoinerRoomDetailView(DetailView):
    model = PublicChatRoom
    template_name = 'detail.html'

    def get_queryset(self):
        return PublicChatRoom.objects.filter(Q(joiners__in=[self.request.user]) | Q(owner=self.request.user)).distinct()

Upvotes: 1

Related Questions