一, 引入

1.为什么要有权限?

2.为什么要开发权限的组件?

3.在web开发中,什么是权限?

4.表结构的设计

权限表

ID

URL

1

/user_list/

2

/customer_list/

用户表

ID

USER_NAME

1

root

2

root 2

角色/用户组表

ID

1

销售

2

开发

用户与角色的关系表

ID

USER_ID

角色ID

1

1

1

2

1

2

3

2

1

4

2

2

角色与权限的关系表

ID

角色ID

权限ID

1

1

1

2

1

2

3

2

1

4

2

2

models:

from django.db import models

# 权限表

class Permission(models.Model):

url = models.CharField(max_length=108, verbose_name='权限')

# 角色表

class Role(models.Model):

name = models.CharField(max_length=108, verbose_name='角色')

permissions = models.ManyToManyField('Permission', verbose_name='角色所拥有的权限', related_name='roles')

# 用户表

class UserInfo(models.Model):

username = models.CharField(max_length=32, verbose_name='用户名')

password = models.CharField(max_length=32, verbose_name='密码')

roles = models.ManyToManyField('Role', verbose_name='用户所拥有的角色', related_name='users')

基本流程:

二, admin的展示

from django.contrib import admin

from rbac import models

# 配置类

class PermissionAdmin(admin.ModelAdmin):

# 展示

list_display = ['title', 'url']

# 可编辑

list_editable = ['url']

admin.site.register(models.Role)

admin.site.register(models.Permission, admin_class=PermissionAdmin)

admin.site.register(models.UserInfo)

三, 记录登录状态与权限

from django.utils.deprecation import MiddlewareMixin

from django.shortcuts import HttpResponse, redirect, reverse

from django.conf import settings

import re

def login(request):

error = ''

if request.method == 'POST':

# 获取用户名和密码

username = request.POST.get('username')

password = request.POST.get('password')

# 数据库校验用户名密码是否正确

user_obj = models.UserInfo.objects.filter(username=username, password=password).first()

if not user_obj:

# 校验失败,返回登录页面

error = '用户名或密码错误'

else:

# 登录成功

# 查询当前用户的权限信息

# permission = models.Permission.objects.filter(roles__users=user_obj).values('url').distinct()

permission = user_obj.roles.all().filter(permissions__url__isnull=False).values('permissions__url').distinct()

# 保存权限信息

request.session['permission'] = list(permission)

request.session['is_login'] = 1

# 重定向去首页

return redirect('index')

return render(request, 'login.html', {'error': error})

四, 中间件校验权限

class Rbac(MiddlewareMixin):

def process_request(self, request):

# 获取当前访问的地址

url = request.path_info

# 白名单

for i in settings.WHITE_LIST:

if re.match(i, url):

return

# 登陆状态的校验

is_login = request.session.get('is_login')

if not is_login:

return redirect('login]')

# 免认证校验

for i in settings.PASS_AUTH_LIST:

if re.match(i, url):

return

# 获取权限信息

permissions = request.session.get('permission')

# 权限的校验

for i in permissions:

if re.match(r'^{}$'.format(i['permissions__url']), url):

return

# 拒绝请求

return HttpResponse('没有访问权限,请联系管理员')

# settings.py中

# rbac 白名单

WHITE_LIST = [

r'^/admin/',

r'^/login/$',

r'^/register/$',

]

# rabc 免认证

PASS_AUTH_LIST =[

r'^/index/$'

]

五, 动态生成一级菜单

首先规范化RBAC:

在settings.py中配置

PERMISSION_SESSION_KEY session中记录权限的key

MENU_SESSION_KEY session中记录菜单信息的key

LOGIN_SESSION_KEY session中记录登录状态的key

将相关template,static,服务等整理到rbac(app)内

model的更改:

# 权限表

class Permission(models.Model):

url = models.CharField(max_length=108, verbose_name='权限')

title = models.CharField(max_length=108, verbose_name='标题')

is_menu = models.BooleanField(default=False, choices=((True, '是'), (False, '否')), verbose_name='是否目录')

icon = models.CharField(max_length=64, verbose_name='图标', null=True, blank=True)

def __str__(self):

return self.title

session记录的更改:

# 查询当前用户的权限信息

# permission = models.Permission.objects.filter(roles__users=user_obj).values('url').distinct()

permission = user_obj.roles.all().filter(permissions__url__isnull=False).values('permissions__url',

'permissions__title',

'permissions__is_menu',

'permissions__icon',

).distinct()

# 权限的列表

permission_list = []

# 菜单的列表

menu_list = []

for i in permission:

permission_list.append({

'url': i['permissions__url']

})

if i.get('permissions__is_menu'):

menu_list.append({

'title': i['permissions__title'],

'icon': i['permissions__icon'],

'url': i['permissions__url']

})

# 保存权限信息

request.session[settings.PERMISSION_SESSION_KEY] = permission_list

request.session[settings.LOGIN_SESSION_KEY] = True

# 保存菜单信息

request.session[settings.MENU_SESSION_KEY] = menu_list

自定义inclusion_tag:

// 插件 menu.html

{% for menu in menu_list %}

{{ menu.title }}

{% endfor %}

from django import template

from django.conf import settings

register = template.Library()

@register.inclusion_tag('rbac/menu.html')

def menu(request):

menu_list = request.session.get(settings.MENU_SESSION_KEY)

url = request.path_info

for menu in menu_list:

if menu.get('url') == url:

menu['class'] = 'active'

return {'menu_list': request.session.get(settings.MENU_SESSION_KEY)}

六, 动态生成二级菜单

model的更改:

# 一级菜单表

class Menu(models.Model):

title = models.CharField(max_length=108, verbose_name='一级菜单标题')

icon = models.CharField(max_length=64, verbose_name='图标', null=True, blank=True)

def __str__(self):

return self.title

# 权限表(二级菜单)

class Permission(models.Model):

'''

menu_id: 有menu_id表示当前的权限是二级菜单

没有menu_id表示当前的权限是普通权限

'''

url = models.CharField(max_length=108, verbose_name='权限')

title = models.CharField(max_length=108, verbose_name='二级菜单标题')

menu = models.ForeignKey('Menu', on_delete=models.CASCADE, verbose_name='一级菜单', null=True, blank=True)

def __str__(self):

return self.title

session记录的更改:

# 查询当前用户的权限信息

# permission = models.Permission.objects.filter(roles__users=user_obj).values('url').distinct()

permission = user_obj.roles.all().filter(permissions__url__isnull=False).values('permissions__url',

'permissions__title',

'permissions__menu__title',

'permissions__menu__icon',

'permissions__menu_id'

).distinct()

# 权限的列表

permission_list = []

# 菜单的字典

menu_dict = {}

for i in permission:

permission_list.append({'url': i.get('permissions__url')})

menu_id = i.get('permissions__menu_id')

if menu_id:

menu_dict.setdefault(menu_id, {

'title': i['permissions__menu__title'],

'icon': i['permissions__menu__icon'],

'children': []

})

menu_dict[menu_id]['children'].append(

{

'title': i['permissions__title'],

'url': i['permissions__url']

}

)

# 保存权限信息

request.session[settings.PERMISSION_SESSION_KEY] = permission_list

request.session[settings.LOGIN_SESSION_KEY] = True

# 保存菜单信息

request.session[settings.MENU_SESSION_KEY] = menu_dict

自定义inclusion_tag:

// 插件中 menu.html

{% for menu_first in menu_list %}

{{ menu_first.title }}

{% for menu_second in menu_first.children %}

{{ menu_second.title }}

{% endfor %}

{% endfor %}

# inclusion_tag

@register.inclusion_tag('rbac/menu.html')

def menu(request):

menu_list = request.session.get(settings.MENU_SESSION_KEY).values()

url = request.path_info

for menu in menu_list:

for i in menu.get('children'):

if i.get('url') == url:

i['class'] = 'active'

return {'menu_list': menu_list}

七, 面包屑导航

model的更改:

# 一级菜单表

class Menu(models.Model):

title = models.CharField(max_length=108, verbose_name='一级菜单标题')

icon = models.CharField(max_length=64, verbose_name='图标', null=True, blank=True)

weight = models.IntegerField(default=1, verbose_name='权重') # 用于一级菜单排序

def __str__(self):

return self.title

# 权限表(二级菜单)

class Permission(models.Model):

url = models.CharField(max_length=108, verbose_name='权限')

title = models.CharField(max_length=108, verbose_name='二级菜单标题')

menu = models.ForeignKey('Menu', on_delete=models.CASCADE, verbose_name='一级菜单', null=True, blank=True)

parent = models.ForeignKey('self', on_delete=models.DO_NOTHING, verbose_name='父权限', null=True, blank=True) # 用于区分二级权限和三级权限,生成面包屑导航

def __str__(self):

return self.title

session记录的更改:

# 查询当前用户的权限信息

# permission = models.Permission.objects.filter(roles__users=user_obj).values('url').distinct()

permission = user_obj.roles.all().filter(permissions__url__isnull=False).values('permissions__url',

'permissions__title',

'permissions__id',

'permissions__parent_id',

'permissions__menu__title',

'permissions__menu__icon',

'permissions__menu__weight',

'permissions__menu_id',

).distinct()

# 权限的字典

permission_dict = {}

# 菜单的字典

menu_dict = {}

for i in permission:

permission_dict[i.get('permissions__id')] = {

'url': i.get('permissions__url'),

'title': i.get('permissions__title'),

'id': i.get('permissions__id'),

'parent_id': i.get('permissions__parent_id')

}

menu_id = i.get('permissions__menu_id')

if menu_id:

menu_dict.setdefault(menu_id, {

'title': i['permissions__menu__title'],

'icon': i['permissions__menu__icon'],

'weight': i['permissions__menu__weight'],

'children': []

})

menu_dict[menu_id]['children'].append(

{

'title': i['permissions__title'],

'url': i['permissions__url'],

'id': i['permissions__id'],

}

)

# 保存权限信息

request.session[settings.PERMISSION_SESSION_KEY] = permission_dict

request.session[settings.LOGIN_SESSION_KEY] = True

# 保存菜单信息

request.session[settings.MENU_SESSION_KEY] = menu_dict

# 此时session记录信息数据格式

# 注意: 存入session中时经过json序列化,字典的key中的数字会转换为字符串

# 权限信息字典

{

1: {

'url': '/customer/list/',

'title': '客户列表',

'id': 1,

'parent_id': None

},

2: {

'url': '/customer/add/',

'title': '添加客户',

'id': 2,

'parent_id': 1

},

3: {

'url': '/customer/edit/(?P\\d+)/',

'title': '编辑客户',

'id': 3,

'parent_id': 1

},

4: {

'url': '/customer/del/(?P\\d+)/',

'title': '删除客户',

'id': 4,

'parent_id': 1

},

5: {

'url': '/payment/list/',

'title': '缴费列表',

'id': 5,

'parent_id': None

},

6: {

'url': '/payment/add/',

'title': '添加缴费',

'id': 6,

'parent_id': 5

},

7: {

'url': '/payment/edit/(?P\\d+)/',

'title': '编辑缴费',

'id': 7,

'parent_id': 5

},

8: {

'url': '/payment/del/(?P\\d+)/',

'title': '删除缴费',

'id': 8,

'parent_id': 5

}

}

# 菜单信息字典

{

1: {

'title': '客户管理',

'icon': 'fa-address-book',

'weight': 10,

'children': [{

'title': '客户列表',

'url': '/customer/list/',

'id': 1

}]

},

2: {

'title': '财务管理',

'icon': 'fa-money',

'weight': 1,

'children': [{

'title': '缴费列表',

'url': '/payment/list/',

'id': 5

}]

}

}

中间件的更改:

class Rbac(MiddlewareMixin):

def process_request(self, request):

# 获取当前访问的地址

url = request.path_info

# 初始化current_menu_id

request.current_menu_id = None

# 初始化导航列表

request.breadcrumb_list = [

{'title': '首页', 'url': '/index/'}

]

# 白名单

for i in settings.WHITE_LIST:

if re.match(i, url):

return

# 登陆状态的校验

is_login = request.session.get(settings.LOGIN_SESSION_KEY)

if not is_login:

return redirect('login')

# 免认证校验

for i in settings.PASS_AUTH_LIST:

if re.match(i, url):

return

# 获取权限信息

permissions = request.session.get(settings.PERMISSION_SESSION_KEY)

# 权限的校验

for i in permissions.values():

# i 权限 父权限 子权限

if re.match(fr'^{i["url"]}$', url):

menu_id = i.get('parent_id')

if not menu_id:

# 当前访问的权限是父权限(二级菜单)

menu_id = i.get('id')

request.breadcrumb_list.append({

'title': i['title'],

'url': i['url']

})

else:

# 当前访问的权限是子权限

parent_permission = permissions[str(menu_id)]

request.breadcrumb_list.append({

'title': parent_permission['title'],

'url': parent_permission['url'],

})

request.breadcrumb_list.append({

'title': i['title'],

'url': i['url'],

})

request.current_menu_id = menu_id

return

# 拒绝请求

return render(request, 'rbac/403.html')

自定义inclusion_tag:

@register.inclusion_tag('rbac/menu.html')

def menu(request):

menu_list = request.session.get(settings.MENU_SESSION_KEY).values()

od_menu_list = sorted(menu_list, key=lambda x: x['weight'], reverse=True)

for menu in od_menu_list:

menu['class'] = 'hidden'

for i in menu.get('children'):

if i.get('id') == request.current_menu_id:

i['class'] = 'active'

menu['class'] = ''

break

return {'menu_list': od_menu_list}

// 插件 menu.html

{% for menu_first in menu_list %}

{{ menu_first.title }}

{% endfor %}

--------------------------------------------------------------

// breadcrumb.html

{% for breadcrumb in breadcrumb_list %}

{% if forloop.last %}

{{ breadcrumb.title }}

{% else %}

{{ breadcrumb.title }}

{% endif %}

{% endfor %}

八, 权限控制到按钮级别

model的更改:

# 权限表(二级菜单)

class Permission(models.Model):

'''

name: 权限控制到按钮级别,判断是否有这个权限

'''

url = models.CharField(max_length=108, verbose_name='权限')

name = models.CharField(max_length=108, verbose_name='url别名', unique=True)

title = models.CharField(max_length=108, verbose_name='二级菜单标题')

menu = models.ForeignKey('Menu', on_delete=models.CASCADE, verbose_name='一级菜单', null=True, blank=True)

parent = models.ForeignKey('self', on_delete=models.DO_NOTHING, verbose_name='父权限', null=True, blank=True)

def __str__(self):

return self.title

session记录的更改:

# 查询当前用户的权限信息

# permission = models.Permission.objects.filter(roles__users=user_obj).values('url').distinct()

permission = user_obj.roles.all().filter(permissions__url__isnull=False).values('permissions__url',

'permissions__title',

'permissions__id',

'permissions__name',

'permissions__parent_id',

'permissions__parent__name',

'permissions__menu__title',

'permissions__menu__icon',

'permissions__menu__weight',

'permissions__menu_id',

).distinct()

# 权限的字典

permission_dict = {}

# 菜单的字典

menu_dict = {}

for i in permission:

permission_dict[i.get('permissions__name')] = {

'url': i.get('permissions__url'),

'title': i.get('permissions__title'),

'id': i.get('permissions__id'),

'parent_id': i.get('permissions__parent_id'),

'parent_name': i.get('permissions__parent__name'),

}

menu_id = i.get('permissions__menu_id')

if menu_id:

menu_dict.setdefault(menu_id, {

'title': i['permissions__menu__title'],

'icon': i['permissions__menu__icon'],

'weight': i['permissions__menu__weight'],

'children': []

})

menu_dict[menu_id]['children'].append(

{

'title': i['permissions__title'],

'url': i['permissions__url'],

'id': i['permissions__id'],

}

)

# 保存权限信息

request.session[settings.PERMISSION_SESSION_KEY] = permission_dict

request.session[settings.LOGIN_SESSION_KEY] = True

# 保存菜单信息

request.session[settings.MENU_SESSION_KEY] = menu_dict

中间件:

# 获取权限信息

permissions = request.session.get(settings.PERMISSION_SESSION_KEY)

# 权限的校验

for i in permissions.values():

# i权限 父权限 子权限

if re.match(fr'^{i["url"]}$', url):

menu_id = i.get('parent_id')

if not menu_id:

# 当前访问的权限是父权限(二级菜单)

menu_id = i.get('id')

request.breadcrumb_list.append({

'title': i['title'],

'url': i['url']

})

else:

# 当前访问的权限是子权限

parent_name = i.get('parent_name')

parent_permission = permissions[parent_name]

request.breadcrumb_list.append({

'title': parent_permission['title'],

'url': parent_permission['url'],

})

request.breadcrumb_list.append({

'title': i['title'],

'url': i['url'],

})

request.current_menu_id = menu_id

return

# 拒绝请求

return render(request, 'rbac/403.html')

自定义tags:

@register.inclusion_tag('rbac/menu.html')

def menu(request):

menu_list = request.session.get(settings.MENU_SESSION_KEY).values()

od_menu_list = sorted(menu_list, key=lambda x: x['weight'], reverse=True)

for menu in od_menu_list:

menu['class'] = 'hidden'

for i in menu.get('children'):

if i.get('id') == request.current_menu_id:

i['class'] = 'active'

menu['class'] = ''

break

return {'menu_list': od_menu_list}

@register.inclusion_tag('rbac/breadcrumb.html')

def breadcrumb(request):

return {

'breadcrumb_list': request.breadcrumb_list

}

@register.filter

def has_permission(request, name):

permission = request.session.get(settings.PERMISSION_SESSION_KEY)

if name in permission:

return True

模板中使用:

{% if request|has_permission:'customer_add' %}

添加客户

{% endif %}

九, 权限管理

# routes.py中

from django.conf import settings

from django.utils.module_loading import import_string

from django.urls import RegexURLResolver, RegexURLPattern

from collections import OrderedDict

def recursion_urls(pre_namespace, pre_url, urlpatterns, url_ordered_dict):

for item in urlpatterns:

if isinstance(item, RegexURLResolver):

if pre_namespace:

if item.namespace:

namespace = "%s:%s" % (pre_namespace, item.namespace,)

else:

namespace = pre_namespace

else:

if item.namespace:

namespace = item.namespace

else:

namespace = None

" None /^ "

recursion_urls(namespace, pre_url + item.regex.pattern, item.url_patterns, url_ordered_dict)

else:

if pre_namespace:

name = "%s:%s" % (pre_namespace, item.name,)

else:

name = item.name

if not item.name:

raise Exception('URL路由中必须设置name属性')

"""

/^^login/$ /login/

"""

url = pre_url + item._regex

url_ordered_dict[name] = {'name': name, 'url': url.replace('^', '').replace('$', '')}

def get_all_url_dict(ignore_namespace_list=None):

"""

获取路由中

:return:

"""

ignore_list = ignore_namespace_list or []

url_ordered_dict = OrderedDict()

md = import_string(settings.ROOT_URLCONF) # 根据路径的字符串 导入模块

urlpatterns = []

for item in md.urlpatterns:

if isinstance(item, RegexURLResolver) and item.namespace in ignore_list:

continue

urlpatterns.append(item)

recursion_urls(None, "/", urlpatterns, url_ordered_dict)

return url_ordered_dict

# views.py

from django.shortcuts import render, redirect, reverse, HttpResponse

from django.views import View

from rbac import models

from django.db.models import Q

from rbac.forms import RoleForm

from rbac.forms import MenuForm

from rbac.forms import PermissionForm

from rbac.forms import MultiPermissionForm

from django.forms import modelformset_factory, formset_factory

from rbac.service.routes import get_all_url_dict

# 展示角色

class RoleList(View):

def get(self, request):

all_role = models.Role.objects.all()

return render(request, 'rbac/role_list.html', {

'all_role': all_role

})

# 新增编辑角色

class RoleChange(View):

def get(self, request, role_id=None, *args, **kwargs):

role_obj = models.Role.objects.filter(pk=role_id).first()

form_obj = RoleForm(instance=role_obj)

return render(request, 'rbac/forms.html', {

'form_obj': form_obj,

})

def post(self, request, role_id=None, *args, **kwargs):

role_obj = models.Role.objects.filter(pk=role_id).first()

form_obj = RoleForm(instance=role_obj, data=request.POST)

if form_obj.is_valid():

form_obj.save()

return redirect('rbac:role_list')

return render(request, 'rbac/forms.html', {

'form_obj': form_obj,

})

# 展示权限信息

class MenuList(View):

def get(self, request):

mid = request.GET.get('mid')

if not mid:

all_permission = models.Permission.objects.all()

else:

all_permission = models.Permission.objects.filter(Q(menu_id=mid) | Q(parent__menu_id=mid))

# all_permission = all_permission.values('id', 'title', 'name', 'url', 'menu_id', 'menu__title', 'parent_id')

permission_dict = {}

for i in all_permission:

menu_id = i.menu_id

id = i.pk

if menu_id:

i.children = []

permission_dict[id] = i

for i in all_permission:

parent_id = i.parent_id

if parent_id:

permission_dict[parent_id].children.append(i)

all_menu = models.Menu.objects.all()

return render(request, 'rbac/menu_list.html', {

'all_menu': all_menu,

'all_permission': permission_dict.values(),

'mid': mid,

})

# 新增编辑菜单

class MenuChange(View):

def get(self, request, menu_id=None, *args, **kwargs):

menu_obj = models.Menu.objects.filter(pk=menu_id).first()

form_obj = MenuForm(instance=menu_obj)

return render(request, 'rbac/menu_form.html', {

'form_obj': form_obj,

})

def post(self, request, menu_id=None, *args, **kwargs):

menu_obj = models.Menu.objects.filter(pk=menu_id).first()

form_obj = MenuForm(instance=menu_obj, data=request.POST)

if form_obj.is_valid():

form_obj.save()

return redirect('rbac:menu_list')

return render(request, 'rbac/menu_form.html', {

'form_obj': form_obj,

})

# 新增编辑权限

class PermissionChange(View):

def get(self, request, permission_id=None, *args, **kwargs):

permission_obj = models.Permission.objects.filter(pk=permission_id).first()

form_obj = PermissionForm(instance=permission_obj)

return render(request, 'rbac/menu_form.html', {

'form_obj': form_obj,

})

def post(self, request, permission_id=None, *args, **kwargs):

permission_obj = models.Permission.objects.filter(pk=permission_id).first()

form_obj = PermissionForm(instance=permission_obj, data=request.POST)

if form_obj.is_valid():

form_obj.save()

return redirect('rbac:menu_list')

return render(request, 'rbac/forms.html', {

'form_obj': form_obj,

})

# 删除

class Delete(View):

def get(self, request, table, pk):

model = getattr(models, table.capitalize())

if not model:

return HttpResponse('非法操作')

obj = model.objects.filter(pk=pk).first()

if not obj:

return HttpResponse('非法操作')

obj.delete()

return redirect(request.META['HTTP_REFERER'])

def multi_permissions(request):

"""

批量操作权限

:param request:

:return:

"""

post_type = request.GET.get('type')

# 编辑 删除

FormSet = modelformset_factory(models.Permission, MultiPermissionForm, extra=0)

# 新增

AddFormSet = formset_factory(MultiPermissionForm, extra=0)

# 数据库所有的权限

permissions = models.Permission.objects.all()

# 路由系统的所有的url 权限

router_dict = get_all_url_dict(ignore_namespace_list=['admin'])

# 数据库权限的name的集合

permissions_name_set = set([i.name for i in permissions])

# 路由系统中权限的name的集合

router_name_set = set(router_dict.keys())

add_name_set = router_name_set - permissions_name_set

add_formset = AddFormSet(initial=[row for name, row in router_dict.items() if name in add_name_set])

if request.method == 'POST' and post_type == 'add':

add_formset = AddFormSet(request.POST)

if add_formset.is_valid():

permission_obj_list = [models.Permission(**i) for i in add_formset.cleaned_data]

query_list = models.Permission.objects.bulk_create(permission_obj_list)

add_formset = AddFormSet()

for i in query_list:

permissions_name_set.add(i.name)

del_name_set = permissions_name_set - router_name_set

del_formset = FormSet(queryset=models.Permission.objects.filter(name__in=del_name_set))

update_name_set = permissions_name_set & router_name_set

update_formset = FormSet(queryset=models.Permission.objects.filter(name__in=update_name_set))

if request.method == 'POST' and post_type == 'update':

update_formset = FormSet(request.POST)

if update_formset.is_valid():

update_formset.save()

update_formset = FormSet(queryset=models.Permission.objects.filter(name__in=update_name_set))

return render(

request,

'rbac/multi_permissions.html',

{

'del_formset': del_formset,

'update_formset': update_formset,

'add_formset': add_formset,

}

)

def distribute_permissions(request):

"""

分配权限

:param request:

:return:

"""

uid = request.GET.get('uid')

rid = request.GET.get('rid')

if request.method == 'POST' and request.POST.get('postType') == 'role':

user = models.UserInfo.objects.filter(id=uid).first()

if not user:

return HttpResponse('用户不存在')

user.roles.set(request.POST.getlist('roles'))

if request.method == 'POST' and request.POST.get('postType') == 'permission' and rid:

role = models.Role.objects.filter(id=rid).first()

if not role:

return HttpResponse('角色不存在')

role.permissions.set(request.POST.getlist('permissions'))

# 所有的用户

user_list = models.UserInfo.objects.all()

# 用户所拥有的角色 id

user_has_roles = models.UserInfo.objects.filter(id=uid).values('id', 'roles')

# 用户所拥有的角色id {角色的id:None }

user_has_roles_dict = {item['roles']: None for item in user_has_roles}

# 所有的角色

role_list = models.Role.objects.all()

if rid:

role_has_permissions = models.Role.objects.filter(id=rid, permissions__id__isnull=False).values('id',

'permissions')

elif uid and not rid:

user = models.UserInfo.objects.filter(id=uid).first()

if not user:

return HttpResponse('用户不存在')

role_has_permissions = user.roles.filter(permissions__id__isnull=False).values('id', 'permissions')

else:

role_has_permissions = []

# 用户 或者 角色所拥有的权限

role_has_permissions_dict = {item['permissions']: None for item in role_has_permissions}

all_menu_list = []

queryset = models.Menu.objects.values('id', 'title') # [ { id title } ]

menu_dict = {}

for item in queryset:

# { id title children:[] }

item['children'] = []

menu_dict[item['id']] = item

all_menu_list.append(item)

other = {'id': None, 'title': '其他', 'children': []}

all_menu_list.append(other)

menu_dict[None] = other

root_permission = models.Permission.objects.filter(menu__isnull=False).values('id', 'title', 'menu_id')

root_permission_dict = {}

for per in root_permission:

# { id title menu_id 'children':[] }

per['children'] = []

nid = per['id']

menu_id = per['menu_id']

root_permission_dict[nid] = per

menu_dict[menu_id]['children'].append(per)

node_permission = models.Permission.objects.filter(menu__isnull=True).values('id', 'title', 'parent_id')

for per in node_permission:

# { id title parent_id }

pid = per['parent_id']

if not pid:

menu_dict[None]['children'].append(per)

continue

root_permission_dict[pid]['children'].append(per)

return render(

request,

'rbac/distribute_permissions.html',

{

'user_list': user_list, # 所有的用户

'role_list': role_list, # 所有的角色

'user_has_roles_dict': user_has_roles_dict, # 用户所拥有的角色

'role_has_permissions_dict': role_has_permissions_dict, # 角色拥有的权限

'all_menu_list': all_menu_list, # 菜单列表

'uid': uid,

'rid': rid

}

)

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐