django 权限不被尊重

django permissions not being respected

如果登录用户具有正确的权限,我会尝试显示一个按钮。

模板中的代码:

  {% if perms.django_apo_training.can_add %}
   <a href="{% url 'training:trainee_add' %}">     
        <button type="button" class="btn btn-success">Add Trainee</button>    
   </a>
   {% endif %}

我可以打印到网页调试用户有什么权限:

  <p> {{ perms.django_apo_training }} </p>

显示:

{'training.view_trainee', 'training.add_trainee', 'training.delete_trainee', 'training.change_trainee'}

但是

perms.django_apo_training.can_add 

总是 returns 错误,不确定我错过了什么?

甚至在管理控制台中仔细检查:

(如果我向相关用户授予超级用户身份,则 if 语句有效并且 returns 正确吗?)

这是实习生的模型

# Create your models here.
class Trainee(models.Model):
    objects = models.Manager()

    first_name = models.CharField(max_length=200)
    last_name = models.CharField(max_length = 200)
    institution = models.CharField(max_length=200, blank=True)
    contact_phone = models.CharField(max_length=50, blank=True)
    contact_email = models.CharField(max_length=100, blank=True)
    trained_date = models.DateField('date trained')

    class Meta:
        ordering = ['institution']

    def __str__(self):
        return "Trainee: " + str(self.first_name) + " " + str(self.last_name) + "   " + str(self.institution)

其次......即使这有效,我如何确保只有拥有该权限并登录的人才能访问(这比 @login 所需的装饰器要多得多)

http://localhost:8000/training/add/

最后:我还创建了使用一对一模型扩展用户模型的模型:

    user = models.OneToOneField(User, on_delete=models.CASCADE)

在我称之为 APOUser 模型的内部,我还有其他字段,我 喜欢 关闭这些权限(特别是 on_site_status 中包含的内容) ), 是否有某种固定方式或 example/recipe 如何做到这一点? (完整模型在这里)

class APOUser(models.Model):
    objects = models.Manager()

    user = models.OneToOneField(User, on_delete=models.CASCADE)

    institution =  models.ForeignKey("mainpage.Institution", on_delete=models.SET_NULL, null=True)
    on_site_status = models.ForeignKey("mainpage.SiteStatus", on_delete=models.SET_NULL,  null=True)
    refer_to_as = models.TextField(max_length = 30, blank=True, null=True) #if the above is custom
    room_preference  = models.ForeignKey("housing.Room", on_delete=models.SET_NULL,  null=True)

创建的标准权限遵循格式<app_label>.view_<model_name>。所以在product以下机型的app中,一共会自动创建8个权限。

class Category(models.Model):
    ...

class Product(models.Model):
    ...

# permissions for the Category model
'product.view_category'
'product.add_category'
'product.change_category'
'product.delete_category'

# permissions for the Product model
'product.view_product'
'product.add_product'
'product.change_product'
'product.delete_product'

在您的示例中 perms.django_apo_training.can_add 将始终 return False 因为没有权限 can_add - 除非您有一个名为 Add 的模型并且已经创建自定义权限。正确的模式应该是 perms.training.add_training.

同样重要的是要注意检查超级用户的权限总是 return True 即使权限不存在。

对于具有权限和自定义用户字段的受保护视图,您可以子类化 UserPassesTestMixin

from django.contrib.auth.mixins import UserPassesTestMixin

def permissions_check(user):
    approved_profile_status = ['ADMIN', 'PURCHASER']
    permission = 'training.add_trainee'

    is_approved = user.profile.on_site_status in approved_profile_status
    has_perm = user.has_perm(permission)
    return is_approved or has_perm


class PermissionsMixin(UserPassesTestMixin):
    def test_func(self):
        return permissions_check(self.request.user)


class TraineeListView(PermissionsMixin, ListView):
    ...