farbodg
farbodg

Reputation: 705

Filtering Django admin console rows based on the logged-in user

I want to restrict which rows appear in the Django admin console based on the user that is logged in. Using the AuthUser model, I have created the following Account model which links Django user accounts to specific businesses in my database:

class Account(models.Model):
    id = models.AutoField(primary_key=True, editable=False)
    username_id = models.ForeignKey('AuthUser', db_column='username_id')
    business_id = models.ForeignKey('Business', db_column='business_id')

Here is my Business model:

class Business(models.Model):
    id = models.AutoField(primary_key=True, editable=False)
    name = models.CharField(max_length=45)
    address = models.CharField(max_length=45)

When the user logs in, I want to restrict the user so they can only add/view/delete entries into/from my database (through the Django admin console) for their respective business. Here is my Entry model:

class Entry(models.Model):
    id = models.AutoField(primary_key=True, editable=False)
    business = models.ForeignKey('Business')
    entry_text = models.CharField(max_length=300)
    created = models.DateField(auto_now=True)

Is there an easy way to get this accomplished?

Upvotes: 1

Views: 883

Answers (1)

Rod Xavier
Rod Xavier

Reputation: 4043

In your model admin, you could override the method get_queryset().

So you could do something like,

 class EntryAdmin(admin.ModelAdmin):
      def get_queryset(self, request):
          qs = super(EntryAdmin, self).get_queryset(request)
          if request.user.is_superuser:
              return qs
          return qs.filter(business__in=request.user.account_set.all().values_list('business_id', flat=True))

The last line, qs.filter(business__in=request.user.account_set.all().values_list('business_id', flat=True)), filters the initial queryset(which defaults to all entries).

request.user.account_set.all() returns all the Account objects associated with the user. Yes, the way you design your Account model will allow multiple objects to be associated to a User. If you want to limit it to one, you should consider using OneToOneField.

Appending .values_list('business_id', flat=True) to the queryset is telling Django that you only want specific columns to be returned, in this case just the business_id column. values_list returns a list of tuples but if you only need one column from the queryset, you can pass the keyword argument flat=True which will return a flat list.

Upvotes: 3

Related Questions