2017-02-14 151 views
3

我使用pytest 3.0.6和pytest-django 3.1.2在Django庫上工作。我有這個非常簡單的測試失敗了,我不明白髮生什麼:Pytest-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='[email protected]', 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='[email protected]', 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 

和DB配置,從測試設置:

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'), 
    }, 
} 

我做錯了什麼?

回答

4

後,您需要使用字符串'app_label.codename'它將工作:

返回true如果用戶擁有指定的權限,在燙髮的格式爲「 <應用程序標籤>。<許可代碼名稱>「。

另外,如果您自上次調用改變的權限,你必須清除user._perm_cacheuser._user_perm_cachehas_perm或檢索從DB該用戶的新實例,以確保沒有緩存:

del john_doe._perm_cache 
del john_doe._user_perm_cache 
# OR 
john_doe = django_user_model.objects.get(username='johndoe') 

這是因爲has_perm將調用auth後端,後者將首先查詢這些緩存。

+0

謝謝你,我完全錯過了緩存系統的權限。 – Antwane

+0

是的。由於緩存沒有很好的記錄,Django可以讓你深入挖掘代碼。 – schwobaseggl

2

docs

has_perm(燙髮,OBJ =無)如果用戶具有指定的權限,其中燙髮的格式爲

"<app label>.<permission codename>"

返回true。

(請參閱有關權限的文檔)。如果用戶處於非活動狀態,則此方法 將始終返回False。

如果傳入了obj,則此方法不會檢查模型的權限,而是檢查此特定對象的權限。

所以這個方法接受字符串不是權限對象

john_doe.has_perm('auth.delete_user')

應該返回True。 (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)