Trying to restrict items to a specific user in a Django Class Based View query set

Viewed 29

I have the following models:

class AccountManager(models.Model):
    account_manager = models.ForeignKey(
      settings.AUTH_USER_MODEL, 
      on_delete=models.CASCADE
    )

    def __str__(self):
        return str(self.account_manager)

class Client(models.Model):
    account_manager = models.ForeignKey(AccountManager, on_delete=models.CASCADE, related_name='account_manager_clients')
    client = models.CharField(max_length=255)

    def __str__(self):
        return self.client

class Contract(models.Model):
    client = models.ForeignKey(Client, on_delete=models.CASCADE, related_name='client_contracts')
    site_name = models.CharField(max_length=255)

    def __str__(self):
        return self.site_name

I can restrict the clients to the specific account managers by using the following view

class ClientListView(LoginRequiredMixin, ListView):
    model = Client
    template_name = "clients/list.html"

    def get_queryset(self, *args, **kwargs):
        return (
            super()
            .get_queryset(*args, **kwargs)
            .filter(account_manager__account_manager=self.request.user)
        )

However I can't seem to restrict the contracts to the account manager with the following view:

class AMContractDetailView(LoginRequiredMixin, DetailView):
    model = Contract
    template_name = 'contracts/am_contract_detail.html'

    def get_queryset(self, *args, **kwargs):
        return (
            super()
            .get_queryset(*args, **kwargs)
            .filter(client__account_manager=self.request.user.id)
        )

This allows account managers to see all the clients not just their own. I know I am doing something fundamentally wrong but have got a bit lost!

Any help would be appreciated.

1 Answers

I'm not sure to totally understand what's the source of the problem here, but I recommend you to opt for another approach, as suggested here in another StackOverflow question: your class-based view AMContractDetailView could inherit from UserPassesTestMixin (cf. Django documentation) to check whether or not the user should be able to see that page.

Otherwise, try to override another method of DetailView, for instance get (all available methods are listed here).

By the way, your views ClientListView and AMContractDetailView have 2 parent methods. To resolve a potential ambiguity when calling super, I think you should explicitly pass arguments to the function, e.g. super(DetailView, self).

Related