前言
一些公司內部的CMS系統存在某些內容讓指定的用戶有權限訪問,這時候可以用django自帶的權限管理進行限制,比較方便。
缺點:django自帶的權限是針對model(模型)的,不能針對單條數據,要針對單條數據需要額外的操作。
默認的權限(add, change, delete, view)
django針對每個模型,生成了四個默認的權限(add, change, delete, view)。例如,我有一個model叫Log,那麼這四個默認權限在數據庫的存儲格式為:
表auth_permission(注:id字段的值是隨便取的,使用python manage.py migrate的時候會自動生成)
id | name | content_type_id | codename |
---|---|---|---|
1 | Can add log | 7 | add_log |
2 | Can change log | 7 | change_log |
3 | Can delete log | 7 | delete_log |
4 | Can view log | 7 | view_log |
字段解釋
id:自動生成的
name: 描述權限的的內容,無太大的實際作用
content_type_id:與django_content_type中的id字段對應
codename:權限表示值,換句話說用add_log來表示用戶對Log模型有新增權限。驗證權限的時候就是驗證這個值
那如果我的模型叫Student呢,把上面表中的log替換成student就行了。
name字段中Can add xx,Can change xx等都是固定的,只有xx是根據模型來的。
同理,codename字段也是一樣,add_xxx,change_xxx。
auth_permission表中content_type_id字段還沒有解釋,先來看下面這張表:
表django_content_type
id | app_label | model |
---|---|---|
1 | admin | logentry |
3 | auth | group |
2 | auth | permission |
4 | auth | user |
5 | contenttypes | contenttype |
6 | sessions | session |
7 | test | log |
字段解釋
id:自增字段;auth_permission表的content_type_id字段就對應這個值
app_label:屬於哪個app包,上面的Log就是test app下的模型
model:模型名字
使用方法
在函數中驗證權限,使用user.has_perm
例如:我們有一個書店,有普通員工A(model User),現在需要去出版社訂購一批書(model Book),我們判斷這個人是否有權利添加(add_book)書籍。
user = User.objects.get(username='A') # has_permission是一個boolean,因為Book模型是放在test app下面的 has_permission = user.has_perm('test.add_book')
為什麼驗證權限的時候前面要加app名,很好理解啊,不同app有同樣名字的權限,到底是驗證哪個呢?
驗證函數是否有執行權限,使用@permission_required
@permission_required def function(): pass
permission_required有三個參數:
perm,描述權限的字符串,格式為:app名.權限。如"auth.add_user",“auth.delete_user”
login_url,如果沒有權限需要跳轉的url字符串,如"/login",“https://www.baidu.com”
raise_exception,boolean值,沒有權限是否觸發PermissionDenied異常,觸發異常則直接返回,不會跳轉到login_url指向的地址
在template上使用權限驗證
第一種寫法
首先,我們需要在app的根目錄下創建一個名為templatetags的包(IDEA會自動在包下創建__init__文件),接著在包裡面創建一個文件my_tags.py,在my_tags.py裡面定義一個過濾器has_permission,使用這個濾器對用戶進行權限驗證,它接收兩個參數:
user,當前登錄的用戶對象
perm,需要驗證的權限字符串
from django import template register = template.Library() @register.filter def has_permisstion(user, perm): if user: return user.has_perm(perm) return False
接著,我們創建一個名為index.html的模板頁面,一定要記得加載標籤文件{% load my_tags %}。
{% load my_tags %}後面的內容只有有權限的人才能看到, {% if request.user|has_permisstion:'test.add_department' %} 我有權限 {% endif %}
目錄結構:
演示結果,我已經登錄過了,並且有權限了:
第二種寫法
使用模板裡面的全局變量perms,例如perms.test.add_department
{% if perms.應用名.權限標識 %} {% endif %}
自定義權限
首先,我在test app的model文件中建立了一個Department模型,然後給他增加了一個自定義權限。
class Department(models.Model): name = models.CharField(null=True, max_length=20) user = models.ManyToManyField(User) one_user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='one_user') class Meta: # permissions是一個元組,記得每組權限後面加逗號,下面是一組權限 permissiOns= ( # (權限,權限描述), ('customize_permission', 'This is my customize permission'), )
執行下面語句進行數據庫同步修改:
python manage.py makemigrations
python manage.py migrate
系統輸出,說明增加成功
>> Migrations for 'test': testmigrations003_auto_20200407_1645.py - Change Meta options on department
打開數據庫驗證,成功。
然後,我們就能像前面一樣使用customize_permission這個權限了。
[kyec555 ] django自帶的權限管理Permission用法說明已經有238次圍觀