Pytest-django:设置用户权限
Pytest-django: set user permissions
我使用 pytest 3.0.6 和 pytest-django 3.1.2 为 Django 开发一个库。我有一个非常简单的测试失败了,我不明白发生了什么:
# test_mytest.py
import pytest
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
@pytest.mark.django_db
def test_user_has_perm(django_user_model):
# Create a new user
john_doe = django_user_model.objects.create_user('johndoe', email='jd@example.com', password='123456')
# Get or create the permission to set on user
user_ct = ContentType.objects.get(app_label='auth', model='user')
p, _ = Permission.objects.get_or_create(content_type=user_ct, codename='delete_user', name="Can delete user")
# User don't have the permission
assert john_doe.has_perm(p) is False
# Set permission to user
john_doe.user_permissions.add(p)
assert john_doe.has_perm(p) is True # ---> FAIL
以防万一,测试结果为:
$ pytest
============================= test session starts =============================
platform win32 -- Python 3.5.3, pytest-3.0.6, py-1.4.32, pluggy-0.4.0
Django settings: testsite.settings (from ini file)
rootdir: D:\Dev\foss\django-modern-rpc, inifile: tox.ini
plugins: pythonpath-0.7.1, django-3.1.2, cov-2.4.0
collected 1 items
modernrpc\tests\test_test_test.py F
================================== FAILURES ===================================
_____________________________ test_user_has_perm ______________________________
django_user_model = <class 'django.contrib.auth.models.User'>
@pytest.mark.django_db
def test_user_has_perm(django_user_model):
# Create a new user
john_doe = django_user_model.objects.create_user('johndoe', email='jd@example.com', password='123456')
# Get or create the permission to set on user
user_ct = ContentType.objects.get(app_label='auth', model='user')
p, _ = Permission.objects.get_or_create(content_type=user_ct, codename='delete_user', name="Can delete user")
# User don't have the permission
assert john_doe.has_perm(p) is False
# Set permission to user
john_doe.user_permissions.add(p)
> assert john_doe.has_perm(p) is True # ---> FAIL
E assert False is True
E + where False = <bound method PermissionsMixin.has_perm of <User: johndoe>>(<Permission: auth | user | Can delete user>)
E + where <bound method PermissionsMixin.has_perm of <User: johndoe>> = <User: johndoe>.has_perm
modernrpc\tests\test_test_test.py:20: AssertionError
========================== 1 failed in 0.32 seconds ===========================
配置块,来自tox.ini:
[pytest]
DJANGO_SETTINGS_MODULE = testsite.settings
norecursedirs = .git __pycache__ build dist venv* .tox .vscode .cache *.egg-info
python_paths = modernrpc/tests
testpaths = modernrpc/tests
python_files = test_*.py dummy_*.py
和数据库配置,来自测试设置:
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'modern_rpc.sqlite3'),
},
}
我做错了什么?
来自docs:
has_perm(perm, obj=None)
Returns True if the user has the specified permission, where perm is in the format
"<app label>.<permission codename>"
.
(see documentation on permissions). If the user is inactive, this method
will always return False.
If obj is passed in, this method won’t check for a permission for the model, but for this specific object.
所以这个方法接受字符串而不是权限对象
john_doe.has_perm('auth.delete_user')
应该returnTrue
。 (delete_user
权限分配了 auth
应用程序,因为您已经使用 user_ct
创建它,其中 user_ct
的应用程序是 auth
)。
但是在您的示例中,这不会立即发生,因为还有一个 permission check caching.
它会在你重新获取你的对象后工作
#Be aware this only works after Django 1.9+
#https://code.djangoproject.com/ticket/26514
john_doe.refresh_from_db()
#Otherwise use:
john_doe = User.objects.get(pk=john_doe.pk)
你需要使用字符串'app_label.codename'
:
Returns True if the user has the specified permission, where perm is in the format "<app label>.<permission codename>".
此外,如果自上次调用 has_perm
后更改了权限,则必须清除 user._perm_cache
和 user._user_perm_cache
,或者从数据库中检索此用户的新实例以确保没有缓存:
del john_doe._perm_cache
del john_doe._user_perm_cache
# OR
john_doe = django_user_model.objects.get(username='johndoe')
这是因为 has_perm
将调用身份验证后端,而后者又将首先查询这些缓存。
我使用 pytest 3.0.6 和 pytest-django 3.1.2 为 Django 开发一个库。我有一个非常简单的测试失败了,我不明白发生了什么:
# test_mytest.py
import pytest
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
@pytest.mark.django_db
def test_user_has_perm(django_user_model):
# Create a new user
john_doe = django_user_model.objects.create_user('johndoe', email='jd@example.com', password='123456')
# Get or create the permission to set on user
user_ct = ContentType.objects.get(app_label='auth', model='user')
p, _ = Permission.objects.get_or_create(content_type=user_ct, codename='delete_user', name="Can delete user")
# User don't have the permission
assert john_doe.has_perm(p) is False
# Set permission to user
john_doe.user_permissions.add(p)
assert john_doe.has_perm(p) is True # ---> FAIL
以防万一,测试结果为:
$ pytest
============================= test session starts =============================
platform win32 -- Python 3.5.3, pytest-3.0.6, py-1.4.32, pluggy-0.4.0
Django settings: testsite.settings (from ini file)
rootdir: D:\Dev\foss\django-modern-rpc, inifile: tox.ini
plugins: pythonpath-0.7.1, django-3.1.2, cov-2.4.0
collected 1 items
modernrpc\tests\test_test_test.py F
================================== FAILURES ===================================
_____________________________ test_user_has_perm ______________________________
django_user_model = <class 'django.contrib.auth.models.User'>
@pytest.mark.django_db
def test_user_has_perm(django_user_model):
# Create a new user
john_doe = django_user_model.objects.create_user('johndoe', email='jd@example.com', password='123456')
# Get or create the permission to set on user
user_ct = ContentType.objects.get(app_label='auth', model='user')
p, _ = Permission.objects.get_or_create(content_type=user_ct, codename='delete_user', name="Can delete user")
# User don't have the permission
assert john_doe.has_perm(p) is False
# Set permission to user
john_doe.user_permissions.add(p)
> assert john_doe.has_perm(p) is True # ---> FAIL
E assert False is True
E + where False = <bound method PermissionsMixin.has_perm of <User: johndoe>>(<Permission: auth | user | Can delete user>)
E + where <bound method PermissionsMixin.has_perm of <User: johndoe>> = <User: johndoe>.has_perm
modernrpc\tests\test_test_test.py:20: AssertionError
========================== 1 failed in 0.32 seconds ===========================
配置块,来自tox.ini:
[pytest]
DJANGO_SETTINGS_MODULE = testsite.settings
norecursedirs = .git __pycache__ build dist venv* .tox .vscode .cache *.egg-info
python_paths = modernrpc/tests
testpaths = modernrpc/tests
python_files = test_*.py dummy_*.py
和数据库配置,来自测试设置:
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'modern_rpc.sqlite3'),
},
}
我做错了什么?
来自docs:
has_perm(perm, obj=None)
Returns True if the user has the specified permission, where perm is in the format
"<app label>.<permission codename>"
.(see documentation on permissions). If the user is inactive, this method will always return False.
If obj is passed in, this method won’t check for a permission for the model, but for this specific object.
所以这个方法接受字符串而不是权限对象
john_doe.has_perm('auth.delete_user')
应该returnTrue
。 (delete_user
权限分配了 auth
应用程序,因为您已经使用 user_ct
创建它,其中 user_ct
的应用程序是 auth
)。
但是在您的示例中,这不会立即发生,因为还有一个 permission check caching.
它会在你重新获取你的对象后工作
#Be aware this only works after Django 1.9+
#https://code.djangoproject.com/ticket/26514
john_doe.refresh_from_db()
#Otherwise use:
john_doe = User.objects.get(pk=john_doe.pk)
你需要使用字符串'app_label.codename'
:
Returns True if the user has the specified permission, where perm is in the format "<app label>.<permission codename>".
此外,如果自上次调用 has_perm
后更改了权限,则必须清除 user._perm_cache
和 user._user_perm_cache
,或者从数据库中检索此用户的新实例以确保没有缓存:
del john_doe._perm_cache
del john_doe._user_perm_cache
# OR
john_doe = django_user_model.objects.get(username='johndoe')
这是因为 has_perm
将调用身份验证后端,而后者又将首先查询这些缓存。