官方解釋
Custom permissions¶
To create custom permissions for a given model object, use the permissions model Meta attribute.
This example Task model creates three custom permissions, i.e., actions users can or cannot do with Task instances, specific to your application:
class Task(models.Model): ... class Meta: permissions = ( ("view_task", "Can see available tasks"), ("change_task_status", "Can change the status of tasks"), ("close_task", "Can remove a task by setting its status as closed"), )
The only thing this does is create those extra permissions when you run manage.py migrate (the function that creates permissions is connected to the post_migrate signal). Your code is in charge of checking the value of these permissions when a user is trying to access the functionality provided by the application (viewing tasks, changing the status of tasks, closing tasks.) Continuing the above example, the following checks if a user may view tasks:
user.has_perm('app.view_task')
項目實戰
定義權限字典
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
name = models.CharField(max_length=64)
school = models.ForeignKey('School')
def __unicode__(self):
return self.name
# 設置3個權限字段,擁有權限者可操作此表(在admin中授權用戶)
class Meta:
permissions = (
('view_customer_list',u"查看客戶列表"), # 權限字段名稱及其解釋
('view_customer_info',u"查看客戶詳情"),
('edit_own_customer_info',u"修改客戶信息"),
)
在APP下新建permissions.py,用於權限匹配控制
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
__Author__ = 'Kongzhagen'
from django.core.urlresolvers import resolve
from django.shortcuts import render,redirect
# 3個權限字段對應三個URL規則,匹配后可操作
perm_dic = {
'view_customer_list':['customer_list','GET',[]], # 權限字段名稱(models表中定義),URL別名,GET方法,請求參數
'view_customer_info':['customer_detail','GET',[]],
'edit_own_customer_info':['customer_detail','POST',['qq','name']], # GET為查詢,POST提交數據
}
def perm_check(*args, **kwargs):
request = args[0]
# 反向解析request中url
url_resovle_obj = resolve(request.path_info)
current_url_namespace = url_resovle_obj.url_name
print "url namespace:",current_url_namespace
matched_flag = False
matched_perm_key = None
# 如果正確反解析出了url且其在權限字典中
if current_url_namespace is not None:
print "find perm item ..."
for perm_key in perm_dic:
perm_val = perm_dic[perm_key]
if len(perm_val) == 3:
url_namespace,request_method,request_args = perm_val
# 如果request中的url、get方法與權限列表中相同
if url_namespace == current_url_namespace:
if request.method == request_method:
# 如果權限列表中無請求參數,此時已可以確定找到了權限規則
if not request_args:
matched_flag = True
matched_perm_key = perm_key
print 'matched perm ...'
break
else:
# 如果權限列表中有請求的參數,反射出request中get或post數據
request_method_func = getattr(request,request_method)
# 如果權限列表中所有請求參數都與反射出的參數匹配,則證明權限匹配成功
for request_arg in request_args:
if request_method_func.get(request_arg) is not None:
matched_flag = True
else:
# 一旦有不匹配的情況,則證明權限已經匹配錯誤,后續無須再做判斷
matched_flag = False
print "request arg[%s] not matched" % request_arg
break
# 如果此條規則匹配成功,不需要再做后續其它規則的匹配
if matched_flag == True:
print "--passed permission check --"
matched_perm_key = perm_key
break
else:
# 如果request解析出的url與urls不匹配,放過???
return True
# request請求與權限規則已匹配
if matched_flag == True:
perm_str = 'crm.%s' % matched_perm_key
# 如果用戶被授與此權限,返回True,否則返回False
if request.user.has_perm(perm_str):
print "\033[42;1m ------ permission checked -------\033[0m"
return True
else:
print "\033[41;1m ------- no permission --------\033[0m"
print request.user,perm_str
return False
else:
print "\033[41;1m ------ no matched permission ----- \033[0m"
def check_permission(func):
def wrapper(*args, **kwargs):
print "--start check perms",args[0]
if not perm_check(*args, **kwargs):
return render(args[0],'crm/403.html')
return func(*args, **kwargs)
return wrapper
修改視圖

設置URLS
from django.conf.urls import url
from django.contrib import admin
import views
urlpatterns = [
url(r'^$', views.dashboard),
url(r'^customers/$', views.customers, name='customer_list'),
url(r'^customers/(\d+)/$', views.customerInfo, name='customer_detail'),
]
驗證
以普通用戶登陸customers,查看客戶列表

用admin給普通用戶授予查看客戶列表權限

再次用普通用戶查看

自定義權限設置成功。。。
