为什么 `user.has_perm(Model, obj)` return False 虽然 `user.has_perm(Model)` return 是 True?

Why does `user.has_perm(Model, obj)` return False although `user.has_perm(Model)` returns True?

在刚刚使用 django-admin startproject./manage.py startapp 创建的 Django 项目和应用程序中,我创建了这个模型:

class Book(models.Model):
    author = models.CharField(max_length=50)

然后我 运行 这个代码 ./manage.py shell:

from django.contrib.auth.models import Permission, User
from django.test import TestCase
from myapp.models import Book

myuser = User.objects.create_user(username="myuser")
myuser.user_permissions.add(Permission.objects.get(codename="change_book"))

mybook = Book(author="Joe Author")
mybook.save()

myuser.has_perm("myapp.change_book"))  # The result is True
myuser.has_perm("myapp.change_book", mybook))  # The result is False

这是为什么?用户 有编辑 mybook 的权限,不是吗? has_perm() 应该如何工作?这在某处记录了吗?

has_perm() API 旨在与模型级权限(第二个参数为 None)和对象级权限一起使用。但是,由个人 authentication backends 决定支持什么。

在 Django 的默认情况下 ModelBackendno support for object-level permissions:

Django’s permission framework has a foundation for object permissions, though there is no implementation for it in the core. That means that checking for object permissions will always return False.

这在ModelBackend documentation中也有注明。

请注意,此处后端必须 return False,因为各个后端的结果本质上是通过“或”运算在一起的。如果这个后端 returned True 就不可能尊重来自其他后端的更细粒度的结果。

还有 个实现对象级权限的后端,django-guardian being perhaps the best known. See how it documents has_perm():

Main difference between Django's ModelBackend is that we can pass obj instance here.