使用django-guardian實(shí)現(xiàn)django-admin的行級(jí)權(quán)限控制的方法
用django框架來做一些后臺(tái)管理的web頁面簡(jiǎn)直太方便了,django自帶模塊級(jí)的權(quán)限系統(tǒng),用來做一些內(nèi)部的系統(tǒng)非常合適,可以大大的減少開發(fā)量。但是django自帶的權(quán)限系統(tǒng)還不支持行級(jí)的權(quán)限控制,如果要實(shí)現(xiàn)行級(jí)的權(quán)限控制,需要依賴第三方的app來開發(fā),或者自己重新寫一個(gè)。
需求描述
我們項(xiàng)目組開發(fā)的一些系統(tǒng)通常會(huì)用mysql數(shù)據(jù)庫來存儲(chǔ)一些配置,但是如果每次有配置修改的時(shí)候都去手動(dòng)修改mysql數(shù)據(jù)的話,會(huì)挺麻煩的,同時(shí)也比較容易出錯(cuò)。django-admin能夠根據(jù)定義的model自動(dòng)的生成相應(yīng)的頁面,同時(shí)還能提供權(quán)限的管理,所以我們就把一些系統(tǒng)到的配置放到django中。但是到現(xiàn)在,隨著系統(tǒng)的需求越來越多,該系統(tǒng)已經(jīng)不止我們自己項(xiàng)目組的人員使用,也要開放給其他項(xiàng)目組的同事使用,所以就產(chǎn)生了一些更細(xì)粒度的權(quán)限需求。因此,我們要在現(xiàn)有的系統(tǒng)上支持行級(jí)的權(quán)限控制。
解決方案
當(dāng)然可以自己寫一套權(quán)限系統(tǒng)了,但是自己寫的成本比較高,而且自己寫的不一定比較好。所以我就先在網(wǎng)上找了一些現(xiàn)成的解決方案, https://djangopackages.org/grids/g/perms/ 該鏈接列出了現(xiàn)有的一些第三方的權(quán)限系統(tǒng)解決方案。從該頁面來看,django-guardian是最受歡迎的第三方權(quán)限系統(tǒng),而且支持行級(jí)的權(quán)限系統(tǒng),同時(shí)還可以整合到django-admin里面,所以我就選擇了django-guardian。
關(guān)鍵步驟
安裝配置django-guardian
安裝配置django-guardian比較簡(jiǎn)單,按照她項(xiàng)目提供的 文檔 進(jìn)行安裝就可以了,安裝完成后會(huì)在數(shù)據(jù)庫里面創(chuàng)建兩張權(quán)限相關(guān)的表。
把django-guardian整合到django-admin
首先把a(bǔ)dmin.py文件里面需要用到行級(jí)權(quán)限的類,由原來的繼承admin.ModelAdmin,改成繼承GuardedModelAdmin,這時(shí)候打開某個(gè)數(shù)據(jù)行的頁面的時(shí)候,在該頁面的右上角的歷史旁邊會(huì)顯示編輯對(duì)象權(quán)限的按鈕,點(diǎn)擊該按鈕進(jìn)去相應(yīng)的頁面就可以編輯該行數(shù)據(jù)的具體權(quán)限。
配置完權(quán)限的時(shí)候,用一個(gè)新的用戶測(cè)試的話,會(huì)發(fā)現(xiàn)該用戶沒有權(quán)限來訪問任何的數(shù)據(jù),這是因?yàn)镚uardedModelAdmin還有很多事情沒有幫我們做,我們還需要重寫一些函數(shù)來實(shí)現(xiàn)admin后臺(tái)頁面的顯示。具體的信息看下面的代碼注釋。
from guardian.admin import GuardedModelAdmin
from guardian.shortcuts import get_objects_for_user, assign_perm, remove_perm, get_users_with_perms, \
get_groups_with_perms
# 需改前
@admin.register(DataAssistantJob)
class DataAssistantJobAdmin(admin.ModelAdmin):
pass
# 修改后
@admin.register(DataAssistantJob)
class DataAssistantJobAdmin(GuardedModelAdmin):
# app是否在主頁面中顯示的話由該函數(shù)決定
def has_module_permission(self, request):
if super().has_module_permission(request):
return True
return self.get_model_objs(request).exists()
# 在顯示數(shù)據(jù)列表額時(shí)候,哪些數(shù)據(jù)顯示,哪些不顯示,由該函數(shù)控制
def get_queryset(self, request):
if request.user.is_superuser:
return super().get_queryset(request)
data = self.get_model_objs(request)
return data
# 內(nèi)部用來獲取某個(gè)用戶有權(quán)限訪問的數(shù)據(jù)行
def get_model_objs(self, request, action=None, klass=None):
opts = self.opts
actions = [action] if action else ['view', 'change', 'delete']
klass = klass if klass else opts.model
model_name = klass._meta.model_name
return get_objects_for_user(user=request.user, perms=[f'{perm}_{model_name}' for perm in actions],
klass=klass, any_perm=True)
# 用來判斷某個(gè)用戶是否有某個(gè)數(shù)據(jù)行的權(quán)限
def has_perm(self, request, obj, action):
opts = self.opts
codename = f'{action}_{opts.model_name}'
if obj:
return request.user.has_perm(f'{opts.app_label}.{codename}', obj)
else:
return self.get_model_objs(request, action).exists()
# 是否有查看某個(gè)數(shù)據(jù)行的權(quán)限
def has_view_permission(self, request, obj=None):
return self.has_perm(request, obj, 'view')
# 是否有修改某個(gè)數(shù)據(jù)行的權(quán)限
def has_change_permission(self, request, obj=None):
return self.has_perm(request, obj, 'change')
# 是否有刪除某個(gè)數(shù)據(jù)行的權(quán)限
def has_delete_permission(self, request, obj=None):
return self.has_perm(request, obj, 'delete')
# 用戶應(yīng)該擁有他新增的數(shù)據(jù)行的所有權(quán)限
def save_model(self, request, obj, form, change):
result = super().save_model(request, obj, form, change)
if not request.user.is_superuser and not change:
opts = self.opts
actions = ['view', 'add', 'change', 'delete']
[assign_perm(f'{opts.app_label}.{action}_{opts.model_name}', request.user, obj) for action in actions]
return result
通過上面的修改,django-admin中的模塊就能夠支持行級(jí)的權(quán)限,并能夠正確的在后臺(tái)頁面中顯示出來,當(dāng)然如果有很多的模塊需要支持行級(jí)的權(quán)限控制,則可以把上面的這些修改寫到一個(gè)新的類中,然后其他想支持行級(jí)權(quán)限的模塊再?gòu)脑撃K繼承就可以了。
總結(jié)
感覺django-guardian和django-admin整合,實(shí)現(xiàn)的不是很好。如果開發(fā)者對(duì)django內(nèi)部的代碼不怎么了解,那么用django-guardian來實(shí)現(xiàn)行級(jí)權(quán)限控制的話會(huì)挺麻煩的,個(gè)人認(rèn)為django-guardian完全可以把和django-admin的整合做到開箱即用的效果,就像django自帶的權(quán)限系統(tǒng)一樣。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Python黑魔法Descriptor描述符的實(shí)例解析
與迭代器和裝飾器等一樣,描述符也是Python編程中的一項(xiàng)高級(jí)技巧,這里我們就來講解Python黑魔法Descriptor描述符的實(shí)例解析:2016-06-06
(手寫)PCA原理及其Python實(shí)現(xiàn)圖文詳解
這篇文章主要介紹了Python來PCA算法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望能給你帶來幫助2021-08-08
Python利用Pytorch實(shí)現(xiàn)繪制ROC與PR曲線圖
這篇文章主要和大家分享一下Python利用Pytorch實(shí)現(xiàn)繪制ROC與PR曲線圖的相關(guān)代碼,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下2022-12-12
詳解Python中的整除運(yùn)算及其應(yīng)用場(chǎng)景
在Python編程中,整除運(yùn)算(也稱為整商運(yùn)算)是一個(gè)常見的操作,它用于計(jì)算兩個(gè)數(shù)相除后的整數(shù)部分,下面就跟隨小編一起來了解一下它的語法,工作原理和實(shí)際應(yīng)用案例吧2024-11-11
python如何繪制極坐標(biāo)輪廓圖contourf
這篇文章主要介紹了python如何繪制極坐標(biāo)輪廓圖contourf問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
python2.7使用plotly繪制本地散點(diǎn)圖和折線圖
這篇文章主要為大家詳細(xì)介紹了python2.7使用plotly繪制本地散點(diǎn)圖和折線圖實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-04-04
對(duì)Python w和w+權(quán)限的區(qū)別詳解
今天小編就為大家分享一篇對(duì)Python w和w+權(quán)限的區(qū)別詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-01-01

