pythondjangodjango-rest-framework

How to add permissions in django admin panel for user?


I have a django app. And I added in the admin panel of django the following permission:

Accounts | account | Can view account

And in the code of admin.py of the accounts app. I have added this:

from django.contrib.auth import get_user_model
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType

from .models import Account
# from .models import *

# Register your models here.
User = get_user_model()

user = User.objects.get(email='n@n.nl')
print(user.has_perm('view_account'))
content_type = ContentType.objects.get_for_model(Account)
permission = Permission.objects.get(
    codename='view_account', content_type=content_type)
user.user_permissions.add(permission)

permissions = Permission.objects.filter(content_type=content_type)

for perm in permissions:
    print(f"Codename: {perm.codename}, Name: {perm.name}")
print(user)


class AccountAdmin(UserAdmin):
    list_display = (
        "email",
        "first_name",
        "last_name",
        "username",
        "last_login",
        "date_joined",
        "is_active",
    )
    list_display_links = ("email", "first_name", "last_name")
    filter_horizontal = (
        'groups',
        'user_permissions',
    )

    readonly_fields = ("last_login", "date_joined")
    ordering = ("-date_joined",)

    list_filter = ()

    User = get_user_model()
    user = User.objects.get(email='n@n.nl')
    content_type = ContentType.objects.get_for_model(Account)
    permission = Permission.objects.get(
        codename='view_account', content_type=content_type)
    user.user_permissions.add(permission)


admin.site.register(Account, AccountAdmin)

acount - models.py:

from django.contrib.auth.models import (
    AbstractBaseUser, BaseUserManager, PermissionsMixin)
from django.db import models
from django.contrib.auth.models import Permission
from .decorators import allowed_users

# Create your models here.


class MyAccountManager(BaseUserManager):
    @allowed_users(allowed_roles=['account_permission'])
    def create_user(self, email, password=None, **extra_field):

        if not email:
            raise ValueError("Gebruiker moet een email adres hebben.")

        if not password:
            raise ValueError("Gebruiker moet een password hebben.")

        user = self.model(email=email, **extra_field)

        user.set_password(password)

        permission = Permission.objects.get(
            codename='DierenWelzijnAdmin | Dier | Can change animal')
        user.user_permissions.add(permission)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, username, password):
        user = self.create_user(
            email=self.normalize_email(email),
            username=username,
            password=password,

        )
        user.is_admin = True
        user.is_active = True
        user.is_staff = True
        user.is_superadmin = True
        user.save(using=self._db)
        return user


class Account(AbstractBaseUser, PermissionsMixin):
    first_name = models.CharField(max_length=50, blank=True)
    last_name = models.CharField(max_length=50, blank=True)
    username = models.CharField(max_length=50, unique=True)
    email = models.EmailField(max_length=100, unique=True)
    phone_number = models.CharField(max_length=50, blank=True)

    # required
    date_joined = models.DateTimeField(auto_now_add=True)
    last_login = models.DateTimeField(auto_now_add=True)
    is_admin = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    is_superadmin = models.BooleanField(default=False)

    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = ["username"]

    objects = MyAccountManager()

    def full_name(self):
        return f"{self.first_name} {self.last_name}"

    def __str__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        return self.is_admin

    def has_module_perms(self, add_label):
        return True

And when I start the django app. I don't get any errors.

But when I login with the account with the user permission. I still see the message:

You don’t have permission to view or edit anything.

And the permissions:

Question: how to add permissions for users?


Solution

  • You are not provided the Account model, but i can imagine the problem:

    For example you have app named accounts: And you want simply to override some functions from User but you dont want to change User model. You have:

    #accounts.models
    from django.contrib.auth import get_user_model
    
    
    # Register your models here.
    User = get_user_model()
    
    class Account(User):
    
        class Meta:
            proxy = True
            verbose_name = "Account"
    
         def __str__(self):
            return f'I override str {self}'
    

    After that you create an admin:

    #accounts.admin
    from django.contrib import admin
    from .models import Account
    
    class AccountAdmin(admin.ModelAdmin):
        ...
        pass
    
    admin.site.register(Account, AccountAdmin)
    

    And after that you add a permission to user:

    user, __ = Account.objects.get_or_create(email='n@n.nl', is_staff=True, is_active=True)
    content_type = ContentType.objects.get_for_model(Account)
    permission = Permission.objects.get(codename='view_account', content_type=content_type)
    user.user_permissions.add(permission)
    

    But if you see on content_type.app_label, you get 'auth' And AccountAdmin.options.app_label -> 'accounts'

    Problem here is in different app_label and proxy models.

    To see you AccountAdmin you should to do:

    ct = ContentType.objects.get_or_create(app_label="accounts", model='account')
    perm = Permission.objects.get_or_create(codename='view_account', content_type=content_type)
    user.user_permissions.add(perm)
    

    I hope it helps.