对于权限表的操作有两种方式,第一种是一个个的权限进行curd,另外一种是批量操作,自动发现django程序中的路由,进行批量curd,首先介绍第一种方式。

因为在列出菜单时,已经将权限列表列出来了,所以权限包括增加、修改以及删除操作

urls.py

...
re_path(r'^permissions/add/$', PermissionAddView.as_view(), name='permissions_add'),
re_path(r'^permissions/edit/(?P<pid>\d+)/$', PermissionEditView.as_view(), name='permissions_edit'),
re_path(r'^permissions/dell/(?P<pid>\d+)/$', PermissionDelView.as_view(), name='permissions_del'),
re_path(r'^multi/permissions/$', multi_permissions, name='multi_permissions'),
...

后台进行处理

from django import forms
from rbac import models class PermissionModelForm(forms.ModelForm): class Meta:
model=models.Permission
fields='__all__' widgets = {
'title': forms.TextInput(attrs={'placeholder': '请输入权限名称', 'class': 'form-control'}),
'url': forms.TextInput(attrs={'placeholder': '请输入url', 'class': 'form-control'}),
'name': forms.TextInput(attrs={'placeholder': '请输入url名称', 'class': 'form-control'}),
'parent': forms.Select(attrs={'class': 'form-control'}),
'menu':forms.Select(attrs={'class': 'form-control'}),
}
help_texts={
'parent':'父级权限,无法作为菜单的权限才需要选择。',
'menu':'选中,表示该权限可以作为菜单;否则,不可做菜单。'
}
error_messages ={
'title':{
'required':'该字段不能为空'
}
} def clean(self):
menu=self.cleaned_data['menu']
parent=self.cleaned_data['parent']
if menu and parent:
self.add_error('menu','菜单和根权限同时只能选择一个')#错误标注在menu字段旁边

PermissionModelForm

from django.shortcuts import render,redirect,HttpResponse
from django.views import View
from rbac.models import *
from rbac.forms.permissions import PermissionModelForm
from django.urls import reverse class PermissionAddView(View):
def get(self,request):
form = PermissionModelForm()
return render(request,'rbac/permission_add.html',{'form':form}) def post(self,request):
form=PermissionModelForm(data=request.POST)
if form.is_valid():
form.save()
return redirect(reverse('rbac:menus_list'))
return render(request,'rbac/permission_add.html',{'form':form}) class PermissionEditView(View): def get(self,request,pid):
permission_obj=Permission.objects.filter(id=pid).first()
if not permission_obj:
return HttpResponse('该权限不存在')
form=PermissionModelForm(instance=permission_obj)
return render(request,'rbac/permission_edit.html',{'form':form}) def post(self,request,pid):
permission_obj=Permission.objects.filter(id=pid).first()
form=PermissionModelForm(data=request.POST,instance=permission_obj)
if form.is_valid():
form.save()
return redirect(reverse('rbac:menus_list'))
return render(request, 'rbac/permission_edit.html', {'form': form}) class PermissionDelView(View): def get(self,request,pid):
Permission.objects.filter(id=pid).first().delete()
return redirect(reverse('rbac:menus_list'))

第二种方式是批量增加

class MultiPermissionForm(forms.Form):
id = forms.IntegerField(
widget=forms.HiddenInput(),
required=False
)
title = forms.CharField(
widget=forms.TextInput(attrs={'class': "form-control"})
)
url = forms.CharField(
widget=forms.TextInput(attrs={'class': "form-control"})
)
name = forms.CharField(
widget=forms.TextInput(attrs={'class': "form-control"})
)
menu_id = forms.ChoiceField(
choices=[(None, '-----')],
widget=forms.Select(attrs={'class': "form-control"}),
required=False, ) parent_id = forms.ChoiceField(
choices=[(None, '-----')],
widget=forms.Select(attrs={'class': "form-control"}),
required=False,
) def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['menu_id'].choices += models.Menu.objects.values_list('id', 'title')
self.fields['parent_id'].choices += models.Permission.objects.filter(parent__isnull=True).exclude(
menu__isnull=True).values_list('id', 'title') def clean_parent_id(self):
menu = self.cleaned_data.get('menu_id')
parent_id = self.cleaned_data.get('parent_id')
if menu and parent_id:
raise forms.ValidationError('菜单和根权限同时只能选择一个')
return parent_id

MultiPermissionForm

利用formset生成批量数据

from rbac.forms.muti_permissions import MultiPermissionForm
from django.shortcuts import render
from django.forms import formset_factory,modelform_factory
from rbac import models
from rbac.services.routes import * def multi_permissions(request):
"""
批量操作权限
:param request:
:return:
"""
post_type = request.GET.get('type') MultiPermissionFormSet = formset_factory(MultiPermissionForm,extra=0) generate_formset = None
update_formset = None if request.method == 'POST' and post_type == 'generate':
print('request.post',request.POST)
formset = MultiPermissionFormSet(request.POST)
if formset.is_valid():
for row_dict in formset.cleaned_data:
models.Permission.objects.create(**row_dict)
else:
generate_formset = formset if request.method == 'POST' and post_type == 'update':
formset = MultiPermissionFormSet(request.POST)
if formset.is_valid():
for row_dict in formset.cleaned_data:
permission_id = row_dict.pop('id')
models.Permission.objects.filter(id=permission_id).update(**row_dict)
else:
update_formset = formset # 1.1 去数据库中获取所有权限
# [{},{}]
permissions = models.Permission.objects.all().values('id', 'title', 'url', 'name', 'menu_id', 'parent_id')
# {'rbac:menu_list':{},'rbac:menu_add':{..}}
permisssion_dict = OrderedDict()
for per in permissions:
permisssion_dict[per['name']] = per # 1.2 数据库中有的所有权限name的集合
permission_name_set = set(permisssion_dict.keys()) # 2.1 获取路由系统中所有的URL
# {'rbac:menu_list':{'url':.... },,,}
router_dict = get_all_url_dict(ignore_namespace_list=['admin',]) for row in permissions:
name = row['name']
if name in router_dict:
router_dict[name].update(row) # 2.2 路由系统中的所有权限name的集合
router_name_set = set(router_dict.keys()) # 需要新建:数据库无、路由有
if not generate_formset:
generate_name_list=router_name_set-permission_name_set
generate_formset = MultiPermissionFormSet(
initial=[row for name, row in router_dict.items() if name in generate_name_list]
) # 需要删除:数据库有、路由无
destroy_name_list = permission_name_set - router_name_set
destroy_formset = [row for name, row in permisssion_dict.items() if name in destroy_name_list] # 需要更新:数据库有、路由有
if not update_formset:
update_name_list = permission_name_set.intersection(router_name_set)
update_formset = MultiPermissionFormSet(
initial=[row for name, row in router_dict.items() if name in update_name_list]
) return render(
request,
'rbac/multi_permissions.html',
{
'destroy_formset': destroy_formset,
'update_formset': update_formset,
'generate_formset': generate_formset,
}
)

获取路由系统中的url

import re
from collections import OrderedDict
from django.conf import settings
from django.utils.module_loading import import_string
from django.urls.resolvers import URLResolver, URLPattern def recursion_urls(pre_namespace, pre_url, valid_urlpattern_list, url_ordered_dict):
"""
递归的去获取URL
:param pre_namespace: namespace前缀,以后用户拼接name
:param pre_url: url前缀,以后用于拼接url
:param urlpatterns: 路由关系列表
:param url_ordered_dict: 用于保存递归中获取的所有路由
:return:
"""
for item in valid_urlpattern_list:
if isinstance(item, URLPattern): # 非路由分发,讲路由添加到url_ordered_dict
if not item.name:
continue
if pre_namespace:
name = "%s:%s" % (pre_namespace, item.name,)
else:
name = item.name
if not item.name:
raise Exception('URL路由中必须设置name属性')
url = pre_url + str(item.pattern)
url_ordered_dict[name] = {'name': name, 'url': url.replace('^', '').replace('$', '')} elif isinstance(item, URLResolver): # 路由分发,递归操作
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
recursion_urls(namespace, pre_url + str(item.pattern), item.url_patterns, url_ordered_dict) def get_all_url_dict(ignore_namespace_list=None):
"""
获取项目中所有的URL(必须有name别名)
:return:
"""
ignore_namespace_list=ignore_namespace_list or []
valid_urlpattern_list=[]
url_ordered_dict = OrderedDict() urlpatterns_list= import_string(settings.ROOT_URLCONF).urlpatterns # from luff.. import urls for urlpattern in urlpatterns_list:
if isinstance(urlpattern, URLResolver):
if urlpattern.namespace in ignore_namespace_list:
continue
else:
valid_urlpattern_list.append(urlpattern)
valid_urlpattern_list.append(urlpattern) recursion_urls(None, '/', valid_urlpattern_list, url_ordered_dict) # 递归去获取所有的路由 return url_ordered_dict

rbac组件之权限操作(四)的更多相关文章

  1. rbac组件之角色操作(二)

    为了与stark组件分离,形成独立的模块,所以rbac数据表的操作需要单独进行操作,对角色表的操作. urls.py urlpatterns = [ re_path(r'^roles/list/$', ...

  2. rbac组件之菜单操作(三)

    菜单包括菜单列表,菜单列表不仅将菜单列出来,而且将每个菜单下的权限也列出来.菜单的添加.删除.修改. urls.py ... re_path(r'^menus/list/$', MenuView.as ...

  3. rbac组件之权限初始化(五)

    当用户登陆后,根据用户的角色要为用户生成对应的权限菜单,此时需要将登陆的用户信息获取且获取角色信息,从数据库中获取菜单以及权限信息,并且存入session中. 1.权限流程 第一次请求的页面是登陆页面 ...

  4. python 全栈开发,Day108(客户管理之权限控制,客户管理之动态"一级"菜单,其他应用使用rbac组件,django static文件的引入方式)

    一.客户管理之权限控制 昨天的作业,有很多不完善的地方 下载代码,基本实现权限验证 https://github.com/987334176/luffy_permission/archive/v1.2 ...

  5. DocX开源WORD操作组件的学习系列四

    DocX学习系列 DocX开源WORD操作组件的学习系列一 : http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_sharp_001_docx1.htm ...

  6. ThinkPHP中RBAC权限带菜单栏显示和详细权限操作

    RBAC是什么,能解决什么难题? RBAC是Role-Based Access Control的首字母,译成中文即基于角色的权限访问控制,说白了也就是用户通过角色与权限进行关联[其架构灵感来源于操作系 ...

  7. Linux学习之CentOS(四)----Linux文件属性、所有者、群组、其他组及文件权限操作简要总结

    Linux文件属性.所有者.群组.其他组及文件权限操作简要总结 首先介绍一个重要的知识点:文件属性控制权限 [root@www ~]# ls -al total 156 drwxr-x--- 4 ro ...

  8. rbac——界面、权限

    一.模板继承 知识点: users.html / roles.html 继承自 base.html 页面滚动时,固定 .menu { background-color: bisque; positio ...

  9. DjangoRestFramework学习三之认证组件、权限组件、频率组件、url注册器、响应器、分页组件

    DjangoRestFramework学习三之认证组件.权限组件.频率组件.url注册器.响应器.分页组件   本节目录 一 认证组件 二 权限组件 三 频率组件 四 URL注册器 五 响应器 六 分 ...

随机推荐

  1. Java SE 第二篇

    二.  Java SE 第二篇 1.  Arrays 数组 // 声明一维数组,[]内不允许有值 int[] arr; int arr[]; // 创建一维数组对象,[]内必须有值 arr = new ...

  2. 【BZOJ3309】DZY Loves Math(线性筛)

    题目: BZOJ 3309 分析: 首先,经过一番非常套路的莫比乌斯反演(实在懒得写了),我们得到: \[\sum_{T=1}^n \sum_{d|T}f(d)\mu(\frac{T}{d})\lfl ...

  3. BZOJ 3224 SBT 普通平衡树

    复习了一下SBT的模板,但是BZOJ不知道为什么注册不了,所以就没交,测了样例能过! #include <bits/stdc++.h> #include<algorithm> ...

  4. 输入一个秒数,要求转换为XX小时XX分XX秒的格式输出出来;

    package arithmetic; import java.util.Scanner; import org.junit.Test; public class Test02 { /** * 输入一 ...

  5. gcc 编译 c++ 程序(转载)

    单个源文件生成可执行程序 下面是一个保存在文件 helloworld.cpp 中一个简单的 C++ 程序的代码: /* helloworld.cpp */ #include <iostream& ...

  6. google breakpad 使用初步总结

    项目地址:https://code.google.com/p/google-breakpad/    访问不了请挂VPN 这是一个由google主导的开源项目,官方介绍为:An open-source ...

  7. Android开发学习--MVP模式入门

    1.模型与视图完全分离,我们可以修改视图而不影响模型2.可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部3.我们可以将一个Presenter用于多个视图,而不需要改变Pr ...

  8. String的用法——获取功能

    package cn.itcast_04; /* String类获取功能 int length():获取字符的长度 char charAt(int index):获取指定索引位置的字符 int ind ...

  9. HTML5应用缓存与Web Workers

    1.什么是应用程序缓存      HTML5引入了应用程序缓存,这意味着web应用可进行缓存,并可在没有因特网链接时进行访问. 2.应用缓存的优势      离线浏览   用户可在应用离线时使用它们 ...

  10. 从源码对比DefaultServeMux 与 gorilla/mux

    从源码对比DefaultServeMux 与 gorilla/mux DefaultServeMux Golang自带的net/http库中包含了DefaultServeMux方法,以此可以搭建一个稳 ...