Django默認提供了權限控制,但只能對使用了其自帶的登錄認證的用戶進行權限控制,說白了就是只能對存儲在auth_user表中的用戶進行權限控制,但不能對未登錄過的用戶進行權限控制。但如果通過集成LDAP認證后的用戶,其用戶也會被緩存到該表中,即變相實現了AD用戶也能進行權限控制。
權限是auth 應用中定義的Permission類型;User與Permission是many-to-many的關系。
Django對於每個模型類,自動增加add、change、delete三種權限,以便於權限控制。當然你也可以設定自己的權限。比如有一個名為hv的model,則該model就有了add、change和delete三種權限,可以在admin后台查看,如下圖所示:
Django可以在view層面進行權限控制,即是否允許某個用戶訪問某個view,使用@permission_required修飾符實現。也可以通過request.user.has_perm() 來對add、change、delete三個動作分別進行權限控制。
一、對某個view進行權限控制,使用@permission_required()修飾符:
如果當前用戶沒有aptest.change_hv權限,則無法訪問add頁面,登錄后依然還會繼續跳回登錄頁面。
from django.contrib.auth.decorators import login_required,permission_required #導入權限控制模塊 @permission_required('aptest.change_hv',login_url="/aptest/loginauth") #第一個參數表示所需要的權限(權限名稱通過user.get_all_permissions()方法查看),第二個參數定義需要登錄到的url,默認為account/login。 def add(request): ...... ......
查看某個用戶當前權限列表:
from django.contrib.auth.models import User user = User.objects.get(username=request.user.username) print user.get_all_permissions() #查看當前用戶所具有的權限列表,返回值是permission name的list #print user.get_group_permissions()方法列出用戶所屬group的權限
返回如下,permission name list:
二、對add、change、delete三個動作分別進行權限控制(比如用戶登錄一個頁面后,可以查看頁面內容,但不能進行增、刪、改動作):
實例:用戶登錄后,判斷是否具有add權限,如果沒有則不能新增條目,實現如下:
編輯view視圖,內容如下:
@login_required(login_url="/aptest/loginauth") #不需要再使用permission_required()裝飾器 def add(request): hvs = hv.objects.all() user = User.objects.get(username=request.user.username) print 'add page: ',user.get_all_permissions()if request.method == 'POST': form = hvform(request.POST) if form.is_valid(): #判斷輸入數據是否合法 #print form.cleaned_data['name'],form.cleaned_data['ip'] fc = form.cleaned_data if request.user.has_perm('aptest.add_hv'): #檢查用戶是否具有add權限,如果沒有則不能保存新增內容 form.save() else: err.append(str(request.user.username) + 'doesnot has add permission.') else: err.append(form.errors) #輸出錯誤信息 else: form = hvform() ls = range(10) context={'hour_offset':hour_offset,'ls':ls,'err':err,'hvs':hvs} return render(request,'aptest/form.html',context)
修改hv model中的一條記錄
from django.shortcuts import get_object_or_404
try: item = get_object_or_404(hv,name=name) form=hvform(request.POST,instance=item) if form.is_valid(): #判斷輸入數據是否合法。如果先用form=hvform(request.POST)去檢查數據是否合法,此處由於name是主鍵,則會報錯,提示該name已存在。 if request.user.has_perm('aptest.change_hv'): #檢查用戶是否具有change權限,如果沒有則不能進行修改 form.save() else: err.append(str(request.user.username) + 'doesnot has change permission.') else: err.append(form.errors.values()[0][0]) #輸出錯誤信息,最好是自定義錯誤信息,此處輸出中文亂碼 except Exception: err...
刪除form中一條記錄,直接item.delete()即可。
User和Group對象Permission管理:
user.user_permissions = [permission_list]
user.user_permissions.add(permission, permission, ...) #增加權限
user.user_permissions.remove(permission, permission, ...) #刪除權限
user.user_permissions.clear() #清空權限
group permission管理邏輯與user permission管理一致,group中使用permissions字段做權限管理:
group.permissions = [permission_list]
group.permissions.add(permission, permission, ...)
group.permissions.remove(permission, permission, ...)
group.permissions.clear()
檢查User或group權限用has_perm()方法:
user.has_perm('appname.add_modelname')
has_perm()方法的參數,即permission的codename,但傳遞參數時需要加上model 所屬app的前綴,格式為<app label>.<permission codename>。
user.get_all_permissions()方法列出用戶的所有權限,返回值是permission name的list
user.get_group_permissions()方法列出用戶所屬group的權限,返回值是permission name的list
檢查用戶所屬組:
dir(request.user.groups)
request.user.groups.values() #返回用戶所屬組
[x['name'] for x in request.user.groups.values()] #返回用戶所屬組
示例:給當前用戶添加hv model的change權限
可以在django_content_type和auth_permission表中查看ContentType、permission中的content_type、codename名稱
from django.contrib.auth.models import Permission from django.contrib.contenttypes.models import ContentType #給當前用戶添加hv model的change權限 user = User.objects.get(username=request.user.username) content_type = ContentType.objects.get_for_model(hv) permission = Permission.objects.get(content_type=content_type, codename='change_hv') request.user.user_permissions.add(permission) #request.user.user_permissions.remove(permission) #刪除當前用戶緩存的權限 if hasattr(user, '_perm_cache'): delattr(user, '_perm_cache') print ,request.user,user.get_all_permissions()
#################################################################################
還可以通過如下方法限制用戶是否可以訪問view(http://www.jb51.net/article/69893.htm):
例如,下面視圖確認用戶登錄並是否有 polls.can_vote權限:
1
2
3
4
5
|
def
vote(request):
if
request.user.is_authenticated()
and
request.user.has_perm(
'polls.can_vote'
)):
# vote here
else
:
return
HttpResponse(
"You can't vote in this poll."
)
|
並且Django有一個稱為 user_passes_test 的簡潔方式。它接受參數然后為你指定的情況生成裝飾器。
1
2
3
4
5
6
7
|
def
user_can_vote(user):
return
user.is_authenticated()
and
user.has_perm(
"polls.can_vote"
)
@user_passes_test
(user_can_vote, login_url
=
"/login/"
)
def
vote(request):
# Code here can assume a logged-in user with the correct permission.
...
|
user_passes_test 使用一個必需的參數: 一個可調用的方法,當存在 User 對象並當此用戶允許查看該頁面時返回 True 。 注意 user_passes_test 不會自動檢查 User是否認證,你應該自己做這件事。