def multi_permissions(request): """ 批量操作权限 :param request: :return: """ post_type = request.GET.get('type') # 删除和编辑使用modelformset FormSet = modelformset_factory(models.Permission, MultiPermissionForm, extra=0) # 添加使用的formset AddFormSet = formset_factory(MultiPermissionForm, extra=0) # 获取数据中所有的权限 permissions = models.Permission.objects.all() # 获取到路由系统所有的url(权限) router_dict = get_all_url_dict(ignore_namespace_list=['admin',]) # 数据库中权限别名的集合 permissions_name_set = set([i.name for i in permissions]) # 路由系统中权限别名的集合 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 multi_permission(request): """ 批量操作权限:获取项目中所有的URL :param request: :return: """ post_type = request.GET.get('type') generate_formset_class = formset_factory(MultiAddPermissionForm, extra=0) update_formset_class = formset_factory(UpdatePermissionForm, extra=0) generate_formset = None update_formset = None if request.method == 'POST' and post_type == 'generate': # 批量添加 formset = generate_formset_class(data=request.POST) if formset.is_valid(): post_row_list = formset.cleaned_data # 用于批量增加 object_list = [] has_errors = False for i in range(0, formset.total_form_count()): row_dict = post_row_list[i] try: new_obj = models.Permission(**row_dict) new_obj.validate_unique() object_list.append(new_obj) except Exception as e: formset.errors[i].update(e) generate_formset = formset has_errors = True if not has_errors: # 如果新添加的数据没有错误,就写入数据库 models.Permission.objects.bulk_create(object_list, batch_size=100) else: generate_formset = formset if request.method == 'POST' and post_type == 'update': # 批量更新 formset = update_formset_class(data=request.POST) if formset.is_valid(): post_row_list = formset.cleaned_data for i in range(0, formset.total_form_count()): row_dict = post_row_list[i] # 取出id,根据id更改数据库中的数据 permission_id = row_dict.pop('id') try: row_object = models.Permission.objects.filter( id=permission_id).first() for k, v in row_dict.items(): setattr(row_object, k, v) row_object.validate_unique() row_object.save() except Exception as e: formset.errors[i].update(e) update_formset = formset else: update_formset = formset # 1.获取项目中所有的url all_url_dict = get_all_url_dict() router_name_set = set(all_url_dict.keys()) """ { 'rbac:menu_add':{'name': 'rbac:menu_add', 'url': '/rbac/menu/menu_add/'}, 'rbac:menu_del':{'name': 'rbac:menu_del', 'url': '/rbac/menu/del/<int:num>/'} ... } """ # 2.获取数据库中所有的URL permission = models.Permission.objects.all().values( 'id', 'title', 'name', 'url', 'menu_id', 'pid_id') permission_ordered_dict = OrderedDict() """ 'customer_list':{'id': 1, 'title': '客户列表', 'name': 'customer_list', 'url': '/customer/list/', 'menu_id': 1, 'pid_id': None} ... """ for row in permission: permission_ordered_dict[row['name']] = row permission_name_set = set(permission_ordered_dict.keys()) # 判断获取的路由URL是否和数据库中URL一致 for name, value in permission_ordered_dict.items(): router_row_dict = all_url_dict.get(name) if not router_row_dict: continue if value['url'] != router_row_dict['url']: value['url'] = '路由和数据库中不一致' # 3.应该添加,删除,修改的权限有哪些 if not generate_formset: generate_name_list = router_name_set - permission_name_set # 应该需要增加的 generate_formset = generate_formset_class(initial=[ row_dict for row, row_dict in all_url_dict.items() if row in generate_name_list ]) # 计算出应该删除的name delete_name_list = permission_name_set - router_name_set # 应该删除的 delete_row_list = [ row_dict for name, row_dict in permission_ordered_dict.items() if name in delete_name_list ] # 计算出应该修改的name。必须要有一个隐藏的id if not update_formset: update_name_list = permission_name_set & router_name_set # 应该更新的 update_formset = update_formset_class(initial=[ row_dict for name, row_dict in permission_ordered_dict.items() if name in update_name_list ]) return render( request, 'rbac/multi_permission.html', { 'generate_formset': generate_formset, 'delete_row_list': delete_row_list, 'update_formset': update_formset })
def multi_permissions(request): """ 批量操作权限 :param request: :return: """ post_type = request.GET.get('type') generate_formset_class = formset_factory(MultiAddPermissionForm, extra=0) update_formset_class = formset_factory(MultiEditPermissionForm, extra=0) generate_formset = None update_formset = None if request.method == 'POST' and post_type == 'generate': # "批量增加" formset = generate_formset_class(data=request.POST) if formset.is_valid(): object_list = [] post_row_list = formset.cleaned_data has_error = False for i in range(0, formset.total_form_count()): row_dict = post_row_list[i] # 拿到每一行的数据 try: new_object = models.Permission(**row_dict) # 实例化一个对象 new_object.validate_unique() object_list.append(new_object) # 用于批量增加 except Exception as e: formset.errors[i].update(e) generate_formset = formset # 页面上去展示错误信息 has_error = True if not has_error: models.Permission.objects.bulk_create( object_list, batch_size=100) # 批量增加100条 else: generate_formset = formset if request.method == 'POST' and post_type == 'update': # "批量更新" formset = update_formset_class(data=request.POST) if formset.is_valid(): post_row_list = formset.cleaned_data for i in range(0, formset.total_form_count()): row_dict = post_row_list[i] permission_id = row_dict.pop('id') try: row_object = models.Permission.objects.filter( id=permission_id).first() for k, v in row_dict.items(): setattr(row_object, k, v) row_object.validate_unique() row_object.save() except Exception as e: formset.errors[i].update(e) update_formset = formset else: update_formset = formset # 1.获取 自动发现 项目中所有的URL all_url_dict = get_all_url_dict() """ all_url_dct = { ' rbac:user_list':{'name': 'rbac:user_list', 'url': '/rbac/user/list/'}, ' rbac:user_add':{'name': 'rbac:user_add', 'url': '/rbac/user/add/'}, ' rbac:user_edit':{'name': 'rbac:user_edit', 'url': '/rbac/user/edit/(?P<pk>\\d+)/'}, ' rbac:user_del':{'name': 'rbac:user_del', 'url': '/rbac/user/del/(?P<pk>\\d+)/'}, }""" router_name_set = set( all_url_dict.keys()) # 获取项目中所有URL的name 'rbac:user_del' # 2.获取数据库中所有的URL permissions = models.Permission.objects.all().values( 'id', 'title', 'name', 'url', 'menu_id', 'pid_id') # QuerySet类型 permission_dict = OrderedDict() permission_name_set = set() # 数据库中的name集合。 for row in permissions: permission_dict[row['name']] = row permission_name_set.add(row['name']) """ permission_dict{ 'rbac:role_list': {'id':1,'title':'角色列表',name:'rbac:role_list',url.....}, 'rbac:role_add': {'id':1,'title':'添加角色',name:'rbac:role_add',url.....}, ... } """ for name, value in permission_dict.items(): router_row_dict = all_url_dict.get(name) if not router_row_dict: continue if value['url'] != router_row_dict['url']: value['url'] = '路由和数据库中不一致,请检查!' # value['url'] = value['url'] +"$$$"+ router_row_dict['url'] # 3.应该添加,删除,修改的权限有哪些 # 3.1 自动发现的权限 "大于" 数据库中的权限 --> 实现批量添加url 的name if not generate_formset: generate_name_list = router_name_set - permission_name_set generate_formset = generate_formset_class(initial=[ row_dict for name, row_dict in all_url_dict.items() if name in generate_name_list ]) # 自动发现有,数据库没有,就放到页面去展示,并批量添加 # 3.2 数据库中的权限 "大于" 自动发现的权限 --> 批量删除 delete_name_list = permission_name_set - router_name_set delete_row_list = [ row_dict for name, row_dict in permission_dict.items() if name in delete_name_list ] # 3.3 自动发现的权限 和数据库中的权限 个数一致,值有不一致的 # {'payment_list', 'payment_del', 'customer_tpl', 'customer_del', 'customer_import', 'payment_add', 'customer_edit', 'payment_edit', 'customer_list', 'customer_add'} if not update_formset: update_name_list = permission_name_set & router_name_set update_formset = update_formset_class(initial=[ row_dict for name, row_dict in permission_dict.items() if name in update_name_list ]) return render( request, 'rbac/multi_permission.html', { 'generate_formset': generate_formset, 'delete_row_list': delete_row_list, 'update_formset': update_formset, })
def multi_permission(request): ''' 批量增改权限 :param request: :return: ''' post_type = request.GET.get('type') formset_add_class = formset_factory(menu.MultiAddPermissionsForm, extra=0) generate_formset = None # 批量新增权限 if request.method == 'POST' and post_type == 'generate': formset = formset_add_class(request.POST) if formset.is_valid(): post_row_list = formset.cleaned_data obj_list = [] has_error = False for i in range(0, formset.total_form_count()): row = post_row_list[i] try: obj = models.Permission(**row) obj.validate_unique() obj_list.append(obj) except Exception as e: formset.errors[i].update(e) generate_formset = formset has_error = True if not has_error: models.Permission.objects.bulk_create( obj_list, batch_size=50) # batch_size=50设置一次批量增加条数 else: generate_formset = formset # 批量更新权限 update_formset_class = formset_factory(menu.MultiUpdatePermissionsForm, extra=0) update_formset = None if request.method == 'POST' and post_type == 'update': formset = update_formset_class(request.POST) if formset.is_valid(): post_update_list = formset.cleaned_data for i in range(0, formset.total_form_count()): update_row = post_update_list[i] permission_id = update_row.pop('pid') try: update_obj = models.Permission.objects.filter( pid=permission_id).first() for k, v in update_row.items(): setattr(update_obj, k, v) update_obj.validate_unique() update_obj.save() except Exception as e: formset.errors[i].update(e) update_formset = formset else: update_formset = formset # 自动发现项目中所有的url auto_get_all_url = routes.get_all_url_dict() router_name_set = set(auto_get_all_url.keys()) # 获取数据库中所有的url permission_list = models.Permission.objects.all().values( 'pid', 'title', 'name', 'url', 'menu_id', 'p_id_id') permission_dict = OrderedDict() for row in permission_list: permission_dict[row['name']] = row permission_name_set = set(permission_dict.keys()) for name, value in permission_dict.items(): router_row_dict = auto_get_all_url.get(name) if not router_row_dict: continue if value['url'] != router_row_dict['url']: value['url'] = '路由和数据库不一致' # 获取待操作权限名称列表 # 待添加权限 if not generate_formset: generate_name_list = router_name_set - permission_name_set generate_formset = formset_add_class(initial=[ row_dict for name, row_dict in auto_get_all_url.items() if name in generate_name_list ]) # 待删除权限 delete_name_list = permission_name_set - router_name_set delete_row_list = [ row_dict for name, row_dict in permission_dict.items() if name in delete_name_list ] # print(delete_row_list) # 待更新权限 if not update_formset: update_name_list = router_name_set & permission_name_set update_formset = update_formset_class(initial=[ row_dict for name, row_dict in permission_dict.items() if name in update_name_list ]) return render( request, 'rbac/multi_permission.html', { 'generate_formset': generate_formset, 'delete_row_list': delete_row_list, 'update_formset': update_formset })
def multi_permission(request): """ 权限的批量操作 :param request: :return: """ # 获取所有的url post_type = request.GET.get('type') # 提交的类型,是新建还是修改 generate_formset_class = formset_factory(menu.MultiPermissionForm, extra=0) update_formset_class = formset_factory(menu.MultiUpdatePermissionForm, extra=0) generate_formset = None update_formset = None if request.method == 'POST' and post_type == 'generate': # 批量添加 formset = generate_formset_class(data=request.POST) if formset.is_valid(): object_list = [] post_row_list = formset.cleaned_data # 临时存储正确数据 has_error = False for i in range(formset.total_form_count()): row_dict = post_row_list[i] try: new_object = models.Permission(**row_dict) new_object.validate_unique() object_list.append(new_object) except Exception as e: formset.errors[i].update(e) generate_formset = formset has_error = True if not has_error: # 没有错的话,多个数据同时添加 models.Permission.objects.bulk_create(object_list, batch_size=100) else: generate_formset = formset if request.method == 'POST' and post_type == 'update': formset = update_formset_class(data=request.POST) if formset.is_valid(): post_row_list = formset.cleaned_data for i in range(formset.total_form_count()): row_dict = post_row_list[i] permission_id = row_dict.pop('id') try: row_object = models.Permission.objects.filter( id=permission_id).first() for k, v in row_dict.items(): setattr(row_object, k, v) row_object.validate_unique() row_object.save() except Exception as e: formset.errors[i].update(e) update_formset = formset else: update_formset = formset # 获取此项目中所有url all_url = get_all_url_dict() router_set = set(all_url.keys()) # 获取数据库中所有url db_url = models.Permission.objects.all().values('id', 'title', 'url', 'name', 'menu_id', 'pid_id') db_url_dict = OrderedDict() db_url_set = set() for item in db_url: db_url_dict[item['name']] = item db_url_set.add(item['name']) # 检测数据库与url中数据,数据条数一致,但数据是否一致 for name, value in db_url_dict.items(): router_row_dict = all_url.get( name) # {'name': 'rbac:role_list', 'url': '/rbac/role/list/'}, if not router_row_dict: continue if value['url'] != router_row_dict['url']: value['url'] = '路由和数据库中不一致' # 应该添加到数据库的权限,数据库没有,url内有,但必须有name别名 if not generate_formset: generate_name_list = router_set - db_url_set generate_formset = generate_formset_class(initial=[ row_dict for name, row_dict in all_url.items() if name in generate_name_list ]) # 应该删除数据库的权限,数据库有,url内没有 delete_name_list = db_url_set - router_set delete_row_list = [ row_dict for name, row_dict in db_url_dict.items() if name in delete_name_list ] # 应该修改的权限,数据库和url内数目一致,但是具体数据不一致 if not update_formset: update_name_list = router_set & db_url_set update_formset = update_formset_class(initial=[ row_dict for name, row_dict in db_url_dict.items() if name in update_name_list ]) return render( request, 'rbac/multi_permissions.html', { 'generate_formset': generate_formset, 'delete_row_list': delete_row_list, 'update_formset': update_formset, })
def multi_permissions(request): ''' 批量操作权限 :param request: :return: ''' post_type = request.GET.get('type') generate_formset_class = formset_factory(MultiAddPermissionForm, extra=0) update_formset_class = formset_factory(MultiEditPermissionForm, extra=0) generate_formset = None if request.method == 'POST' and post_type == 'generate': # pass #批量添加 formset = generate_formset_class(data=request.POST) if formset.is_valid(): object_list = [] post_row_list = formset.cleaned_data has_error = False for i in range(0, formset.total_form_count()): row_dict = post_row_list[i] # row_dict 表示每一行的数据 try: # 判断新记录对象在数据库中是否符合索引唯一的约束条件 new_object = models.Permission(**row_dict) # 用行数据实例化一个对象 new_object.validate_unique() object_list.append(new_object) except Exception as e: formset.errors[i].update(e) # 校验索引唯一失败,更新错误信息 generate_formset = formset # 这行目的是在页面上显示错误信息 has_error = True if not has_error: # 没有错误才可以批量增加 models.Permission.objects.bulk_create( object_list, batch_size=100) # 没有错误信息时,批量增加100条数据 else: # 如果formset校验失败,含校验错误数据的formset 赋值给generate_formset, 不再初始化生成formset数据 generate_formset = formset # 包含校验错误数据的formset 赋值给generate_formset update_formset = None if request.method == 'POST' and post_type == 'update': # pass #批量更新 formset = update_formset_class(data=request.POST) if formset.is_valid(): post_row_list = formset.cleaned_data for i in range(0, formset.total_form_count()): row_dict = post_row_list[i] permission_id = row_dict.pop('id') try: row_object = models.Permission.objects.filter( id=permission_id).first() for k, v in row_dict.items( ): # 利用反射将row_dict的数据(校验后的页面数据)设置到row_object, k,v setattr(row_object, k, v) row_object.validate_unique() row_object.save() # 由于是更新,不能批量插入数据库 except Exception as e: formset.errors[i].update(e) update_formset = formset else: update_formset = formset # 1. 获取项目中所有的URL all_url_dict = get_all_url_dict() ''' { rbac:role_list {'name': 'rbac:role_list', 'url': '/rbac/role/list/'} rbac:role_add {'name': 'rbac:role_add', 'url': '/rbac/role/add/'} rbac:role_edit {'name': 'rbac:role_edit', 'url': '/rbac/role/edit/(?P<pk>\\d+)/'} } ''' router_name_set = set(all_url_dict.keys()) # 项目中所有URL的name 集合 # 2. 获取数据库中所有的URL permissions = models.Permission.objects.all().values( 'id', 'title', 'name', 'url', 'menu_id', 'pid_id') # 返回一个Queryset类型 permission_dict = OrderedDict() permission_name_set = set() for row in permissions: permission_dict[row['name']] = row permission_name_set.add(row['name']) # 将数据库中的URL添加到集合中 ''' { 'rbac:role_list': {'id':1, 'title': '角色列表', 'name': 'rbac:role_list', url....}, 'rbac:role_add': {'id':2, 'title': '添加角色', 'name': 'rbac:role_add', url....}, .... } ''' for name, value in permission_dict.items(): router_row_dict = all_url_dict.get( name) # {'name': 'rbac:role_list', 'url': '/rbac/role/list/'} if not router_row_dict: # 当数据库中有name, 但自动发现中没有name, ,在更新操作中处理,先跳过当前循环 continue if value['url'] != router_row_dict[ 'url']: # 如果数据库中name对应的URL, 与自动发现name对应的url不相等 value['url'] = '自动发现URL和数据库URL中不一致' # print("permission_dict:",permission_dict) # 3. 应该添加,删除,修改的权限有哪些 # 3.1 计算出应该增加的name # 如果generate_formset不为None, 说明提交的请求是POST,不再初始化生成generate_formset数据,使用提交的generate_formset数据 # 如果generate_formset为None, 说明提交的请求是GET , generate_formset 初始化生成数据 if not generate_formset: print("generate_formset:", generate_formset) generate_name_list = router_name_set - permission_name_set # 自动发现name数量 大于 数据库中name数量, 求差集 # generate_formset_class = formset_factory(MultiAddPermissionForm, extra=0) #该行移动到本函数的顶部 # generate_formset_class(initial=[{'name': 'rbac:role_list', 'url': '/rbac/role/list/'},{'name': 'rbac:role_add', 'url': '/rbac/role/add/'}]) #initial示例 generate_formset = generate_formset_class(initial=[ row_dict for name, row_dict in all_url_dict.items() if name in generate_name_list ]) # 列表生成式 # 3.2 计算出应该删除的name delete_name_list = permission_name_set - router_name_set # 数据库中name数量 大于 自动发现name数量 求差集 delete_row_list = [ row_dict for name, row_dict in permission_dict.items() if name in delete_name_list ] # print("delete_row_list:", delete_row_list) # 3.3 计算出应该更新的name if not update_formset: update_name_list = permission_name_set & router_name_set # 取两个集合的交集, 即集合1与集合2 都有的数据 # update_formset_class = formset_factory(MultiEditPermissionForm, extra=0) #这行代码移动到上面了 update_formset = update_formset_class(initial=[ row_dict for name, row_dict in permission_dict.items() if name in update_name_list ]) # ?? # print("update_formset",update_formset) # print("all_url_dict:",all_url_dict) # for k,v in all_url_dict.items(): # print(k,v) ''' 输出结果: rbac:role_list {'name': 'rbac:role_list', 'url': '/rbac/role/list/'} rbac:role_add {'name': 'rbac:role_add', 'url': '/rbac/role/add/'} rbac:role_edit {'name': 'rbac:role_edit', 'url': '/rbac/role/edit/(?P<pk>\\d+)/'} rbac:role_del {'name': 'rbac:role_del', 'url': '/rbac/role/del/(?P<pk>\\d+)/'} rbac:user_list {'name': 'rbac:user_list', 'url': '/rbac/user/list/'} rbac:user_add {'name': 'rbac:user_add', 'url': '/rbac/user/add/'} rbac:user_edit {'name': 'rbac:user_edit', 'url': '/rbac/user/edit/(?P<pk>\\d+)/'} rbac:user_del {'name': 'rbac:user_del', 'url': '/rbac/user/del/(?P<pk>\\d+)/'} rbac:user_reset_pwd {'name': 'rbac:user_reset_pwd', 'url': '/rbac/user/reset/password/(?P<pk>\\d+)/'} rbac:menu_list {'name': 'rbac:menu_list', 'url': '/rbac/menu/list/'} rbac:menu_add {'name': 'rbac:menu_add', 'url': '/rbac/menu/add/'} rbac:menu_edit {'name': 'rbac:menu_edit', 'url': '/rbac/menu/edit/(?P<pk>\\d+)/'} rbac:menu_del {'name': 'rbac:menu_del', 'url': '/rbac/menu/del/(?P<pk>\\d+)/'} rbac:second_menu_add {'name': 'rbac:second_menu_add', 'url': '/rbac/second/menu/add/(?P<menu_id>\\d+)/'} rbac:second_menu_edit {'name': 'rbac:second_menu_edit', 'url': '/rbac/second/menu/edit/(?P<pk>\\d+)/'} rbac:second_menu_del {'name': 'rbac:second_menu_del', 'url': '/rbac/second/menu/del/(?P<pk>\\d+)/'} rbac:permission_add {'name': 'rbac:permission_add', 'url': '/rbac/permission/add/(?P<second_menu_id>\\d+)/'} rbac:permission_edit {'name': 'rbac:permission_edit', 'url': '/rbac/permission/edit/(?P<pk>\\d+)/'} rbac:permission_del {'name': 'rbac:permission_del', 'url': '/rbac/permission/del/(?P<pk>\\d+)/'} rbac:multi_permissions {'name': 'rbac:multi_permissions', 'url': '/rbac/multi/permissions/'} customer_layout {'name': 'customer_layout', 'url': '/layout'} ''' return render( request, 'rbac/multi_permissions.html', { 'generate_formset': generate_formset, 'delete_row_list': delete_row_list, 'update_formset': update_formset, })
def multi_permissions(request): """ 批量操作权限 :param request: :return: """ post_type = request.GET.get('type') generate_formset_class = formset_factory(MultiAddPermissionForm, extra=0) update_formset_class = formset_factory(MultiEditPermissionForm, extra=0) generate_formset = None # 出错了赋值,为了返回给页面错误信息 update_formset = None # 出错了赋值,为了返回给页面错误信息 # 批量添加 if request.method == 'POST' and post_type == 'generate': formset = generate_formset_class(data=request.POST) # 储存的所有信息,包括html标签 if formset.is_valid(): has_repeat_error = False permission_obj_list = [] url_form_list = formset.cleaned_data for num in range(0, formset.total_form_count()): url_form = url_form_list[num] # 下面的方式和model.Permission.object.create(**row)效果一样,这里用这种方式是为了捕获唯一性错误 try: permission_obj = models.Permission(**url_form) permission_obj.validate_unique() # 检查当前对象在数据库是否存在唯一的 permission_obj_list.append(permission_obj) except Exception as e: formset.errors[num].update(e) # 把错误信息放到对应的form里面 generate_formset = formset # 要把用户批量增加时出错的错误信息传给模板 has_repeat_error = True if not has_repeat_error: models.Permission.objects.bulk_create( permission_obj_list, batch_size=formset.total_form_count()) else: generate_formset = formset # 出错信息传给模板 # 批量更新 if request.method == 'POST' and post_type == 'update': formset = update_formset_class(data=request.POST) if formset.is_valid(): url_form_list = formset.cleaned_data for num in range(0, formset.total_form_count()): url_form = url_form_list[num] permission_id = url_form.pop('id') try: permission_obj = models.Permission.objects.filter( id=permission_id).first() for key, value in url_form.items(): setattr(permission_obj, key, value) permission_obj.validate_unique() permission_obj.save() except Exception as e: formset.errors[num].update(e) update_formset = formset # 要把用户批量更新时出错的错误信息传给模板 else: update_formset = formset # 出错信息传给模板 # 1. 获取项目中所有的url all_url_dict = get_all_url_dict() router_name_set = set(all_url_dict.keys()) # 所有路由中的url集合 """ set里不能有重复的值,转换成set后只会剩下key { 'rbac:menu_list': {'name': 'rbac:menu_list', 'url': 'xxxxx/yyyy/menu/list'} } 会变成 {'rbac:menu_list'} """ # # 2. 获取数据库中所有的url all_db_permissions = models.Permission.objects.all().values( 'id', 'title', 'name', 'url', 'menu_id', 'pid_id') db_permission_name_set = set() # 数据库中的set集合 db_permission_dict = OrderedDict() for db_permission in all_db_permissions: db_permission_dict[db_permission[ 'name']] = db_permission # {'rbac:menu_list':{'id':1,'title':'角色列表',name:'rbac:role_list',url:'/rbac/role/list'},} db_permission_name_set.add( db_permission['name']) # {'rbac:menu_list','rbac:menu_add'......} for name, value in db_permission_dict.items(): router_row_dict = all_url_dict.get( name) # {'name':'rbac:role_list','url':'/rbac/role/list'}, if not router_row_dict: # 没有别名和url的直接跳过 continue if value['url'] != router_row_dict['url']: # 数据库里的url和自动发现的url进行对比 value['url'] = '路由和数据库中的不一致' # 字典里的值和列表里的值用的是同一个内存地址,如果改了字典里的值,列表里相应的值也会被改。 # 所以这个操作会修改数据库里url的值为:路由和数据库中的不一致' # 3. 应该添加、删除和修改的权限 # 3.1 计算出应该添加的name if not generate_formset: """ 如果目标没有通过验证,generate_formset的值就是上面出错了的formset,就不会执行下面的代码,页面就会显示错误信息 如果通过验证,就会返回给页面自动发现的数据库中有、路由中没有的url。 下面的 if not update_formset同理 """ generate_name_list = router_name_set - db_permission_name_set generate_formset = generate_formset_class(initial=[ add_url for name, add_url in all_url_dict.items() if name in generate_name_list ]) # 3.2 计算出应该删除的name : 数据库有,路由中没有 delete_url_name_list = db_permission_name_set - router_name_set # 数据库里的url - 路由中的url delete_url_list = [ delete_url_obj for name, delete_url_obj in db_permission_dict.items() if name in delete_url_name_list ] # 3.3 计算出应该更新的name :数据库和路由中都有 if not update_formset: update_name_list = db_permission_name_set & router_name_set # 都包含的元素 update_formset = update_formset_class(initial=[ update_url for name, update_url in db_permission_dict.items() if name in update_name_list ]) context = { 'generate_formset': generate_formset, 'delete_url_list': delete_url_list, 'update_formset': update_formset, } return render(request, 'rbac/multi_permissions.html', context)
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']) # 数据库中的所有权限的别名 permissions_name_set = set([i.name for i in permissions]) # 路由系统中的所有权限的别名 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(): print(add_formset.cleaned_data) permission_obj_list = [ models.Permission(**i) for i in add_formset.cleaned_data ] query_list = models.Permission.objects.bulk_create( permission_obj_list) for i in query_list: permissions_name_set.add(i.name) add_formset = AddFormSet() else: print(add_formset.errors) 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 bulk_operate(request): """ 权限批量操作, 基于三点 1. formset实现批量数据 可以尝试使用modelformset 注意: 在进行保存的时候,如果是添加的话,可以将对象存在一个列表中,之后批量创建,但是更新的话需要每个对象都保存 并且,因为数据库中表的某些字段存在唯一性约束,所以需要判断,如果重复,提示用户,并且提交失败 2. 自动发现项目中的url 获取当前url的时候利用的是urlpattern和resolverpattern 3. 利用set的集合运算 项目中的集合: set_project 数据库中的集合: set_db 批量更新: 项目中存在的url,但是在数据库中不存在 set_project - set_db 批量删除: 数据库中存在的url,项目中不存在 set_db - set_project 不推荐进行批量删除操作,推荐让用户自行绝对删除 批量更新: 数据库和项目中都存在的 set_db & set_project 这里需要注意一点,推荐对url进行对比,之后显示出来的时候提示数据库中的项目中的是否一致,如果一致,可以更新,否则需要 处理,在url字段部分显示数据库和项目中不匹配来提醒用户 :param request: :return: """ create_formset_class = formset_factory(BatchAddPermissionsForm, extra=0) create_formset = None update_formset_class = formset_factory(BatchUpdatePermissionsForm, extra=0) update_formset = None operate_type = request.GET.get("type") if request.method == "POST": if operate_type == "create": create_formset = create_formset_class(request.POST) if create_formset.is_valid(): post_row_list = create_formset.cleaned_data bulk_create_list = [] flag = True for index in range(0, create_formset.total_form_count()): try: row = post_row_list[index] create_obj = models.Permission(**row) create_obj.validate_unique() bulk_create_list.append(create_obj) print(create_obj) except ValidationError as e: create_formset.errors[index].update(e) flag = False if flag: models.Permission.objects.bulk_create(bulk_create_list) elif operate_type == "update": update_formset = update_formset_class(request.POST) if update_formset.is_valid(): post_row_list = update_formset.cleaned_data for index in range(0, update_formset.total_form_count()): try: row = post_row_list[index] update_obj = models.Permission.objects.get( pk=row['id']) if not update_obj: return HttpResponse("该权限不存在,提交失败") update_obj.validate_unique() update_obj.save() except ValidationError as e: create_formset.errors[index].update(e) elif operate_type == "delete": pid = request.GET.get('pid') permission = models.Permission.objects.get(pk=pid) if not permission: return HttpResponse("权限不存在,删除失败") permission.delete() return redirect(reverse_url_v(request, "rbac:bulk_operate")) # 获取集合 db_url_set = set() permissions = models.Permission.objects.all().values( 'id', 'title', 'name', 'url', 'menu_id', 'sub_menu_id') permission_dict = {} for item in permissions: permission_dict[item['name']] = item db_url_set.add(item['name']) project_url_dict = retrieve_project_urls() project_url_set = set(project_url_dict.keys()) # 判断项目中的url和数据库中的url是否相等,因为修改的时候是以数据库为准的,所以这里会修改数据库的value值提示异常 # 批量添加 bulk_create_set = project_url_set - db_url_set if not create_formset: create_formset = create_formset_class(initial=[ value for name, value in project_url_dict.items() if name in bulk_create_set ]) # 删除 delete_set = db_url_set - project_url_set delete_list = [ value for name, value in permission_dict.items() if name in delete_set ] # 批量修改 bulk_update_set = project_url_set & db_url_set if not update_formset: update_formset = update_formset_class(initial=[ value for name, value in permission_dict.items() if name in bulk_update_set ]) return render( request, "rbac/batch_operate.html", { 'create_formset': create_formset, 'delete_list': delete_list, 'update_formset': update_formset, })
def multi_permissions(request): """ 批量操作权限 :param request: :return: """ # for k, v in url_ordered_dict.items(): # print(k, v) # 1、自动获取项目中的URL url_ordered_dict = get_all_urls_dict() ''' { "rbac:menu_list": {"name": "rbac:menu_list", "url":"/rbac/menu/list"}, "rbac:menu_add": {"name": "rbac:menu_add", "url":"/rbac/menu/add"}, } ''' # 获取数据name的集合 url_ordered_set = set(url_ordered_dict.keys()) # 2、获取数据库中的所有url相关信息 permission_url_info = models.Permission.objects.all().values() # [{},……] permission_url_dict = OrderedDict() ''' { "rbac:menu_list": {"title":"菜单列表", "name": "rbac:menu_list", "url":"/rbac/menu/list"……}, "rbac:menu_add": {"title":"增加菜单", "name": "rbac:menu_add", "url":"/rbac/menu/add"……}, } ''' permission_url_set = set() for item in permission_url_info: permission_url_dict[item["name"]] = item permission_url_set.add(item["name"]) # 获取数据name的集合 # --增加一条判断,permission与自动获取url中的name值相同,但url可能不同,需要校验数据 for name, value in permission_url_dict.items(): url_value = url_ordered_dict.get(name) if url_value: if value["url"] != url_value["url"]: value["url"] = "数据库中的URL与路由不一致" # 3、根据数据库中的url与自动获取的url之间进行一个对比,然后增加、更新、删除操作 # 3.1向数据库增加数据 generate_url = url_ordered_set - permission_url_set # 3.1.1 获取所有的增加url及相关信息字典并创建多表验证 formset_add_class = formset_factory(MultiPermissionAdd, extra=0) generate_url_list = [ item for name, item in url_ordered_dict.items() if name in generate_url ] formset_add = formset_add_class(initial=generate_url_list) # 3.2从数据库删除数据 delete_url = permission_url_set - url_ordered_set delete_url_list = [ item for name, item in permission_url_dict.items() if name in delete_url ] # 3.3向数据库更新数据 update_url = permission_url_set & url_ordered_set update_url_dict = [ item for name, item in permission_url_dict.items() if name in update_url ] formset_update_class = formset_factory(MultiPermissionUpdate, extra=0) formset_update = formset_update_class(initial=update_url_dict) # 通过get数据中的?type=generate获取具体的type数据 type_data = request.GET.get("type") # 新增数据 if request.method == "POST" and type_data == "generate": formset_add = formset_add_class(data=request.POST) if formset_add.is_valid(): # 数据校验成功 # [{'title': '客户列表', 'url': '/customer/list/', 'name': 'customer_list', 'menu_id': '1', 'pid_id': ''}……] clean_data_list = formset_add.cleaned_data object_lists = [] # 创建一个列表用于存放所有的对象,后面一次性添加至数据库 err_status = False for index in range(formset_add.total_form_count()): row_data = clean_data_list[index] try: per_add_obj = models.Permission(**row_data) per_add_obj.validate_unique() # 校验字段中的唯一性 object_lists.append(per_add_obj) except Exception as e: # 将错误信息放入errors中,用于展示到页面中 formset_add.errors[index].update(e) err_status = True # 当所有的数据校验无误后,将所有数据对象添加进数据库中 if not err_status: # 批量添加数据-batch_size一次性向数据库中添加的数据量 models.Permission.objects.bulk_create(object_lists, batch_size=100) # 如果失败,将formset_add的数据及错误信息显示在前端页面中 # 更新数据 if request.method == "POST" and type_data == "update": formset_update = formset_update_class(data=request.POST) if formset_update.is_valid(): # 数据校验成功 clean_data_list = formset_update.cleaned_data for index in range(formset_update.total_form_count()): row_data = clean_data_list[index] # 'id': 12, 获取主键 update_id = row_data.pop("id") try: update_obj = models.Permission.objects.filter( id=update_id).first() # 将传入的数据添加进当前对象中,再进行数据校验 for k, v in row_data.items(): setattr(update_obj, k, v) update_obj.validate_unique() update_obj.save() except Exception as e: formset_update.errors[index].update(e) return render( request, "rbac/multi_permissions.html", { "formset_add": formset_add, "delete_url_list": delete_url_list, "formset_update": formset_update })
def multi_permission(request): post_type = request.GET.get('type') formset_add_class = formset_factory(MultiAddPermissionsForm, extra=0) update_formset_class = formset_factory(MultiUpdatePermissionsForm, extra=0) generate_formset = None update_formset = None # 添加url if request.method == 'POST' and post_type == 'generate': formset = formset_add_class(request.POST) if formset.is_valid(): post_row_list = formset.cleaned_data obj_list = [] has_error = False for i in range(0, formset.total_form_count()): row = post_row_list[i] try: obj = models.Permission(**row) obj.validate_unique() # 判断唯一性 obj_list.append(obj) except Exception as e: formset.errors[i].update(e) generate_formset = formset has_error = True if not has_error: models.Permission.objects.bulk_create(obj_list, batch_size=50) else: generate_formset = formset # 更新url if request.method == 'POST' and post_type == 'update': formset = update_formset_class(request.POST) if formset.is_valid(): post_update_list = formset.cleaned_data for i in range(0, formset.total_form_count()): update_row = post_update_list[i] print(update_row) permission_id = update_row.pop('id') try: update_obj = models.Permission.objects.filter( id=permission_id).first() for k, v in update_row.items(): setattr(update_obj, k, v) update_obj.validate_unique() update_obj.save() except Exception as e: formset.errors[i].update(e) update_formset = formset else: update_formset = formset # 获得程序和数据库中的url auto_get_all_url = routes.get_all_url_dict() routes_name_set = set(auto_get_all_url.keys()) permission_list = models.Permission.objects.all().values( 'id', 'title', 'url', 'name', 'menu_id', 'pid_id') permission_dict = OrderedDict() for item in permission_list: permission_dict[item['name']] = item permission_set = set(permission_dict.keys()) for name, value in permission_dict.items(): router_row_dict = auto_get_all_url.get(name) if not router_row_dict: continue if value['url'] != router_row_dict['url']: value['url'] = '路由和数据库中不一致!' # 待增加的url if not generate_formset: generate_name_list = routes_name_set - permission_set generate_formset = formset_add_class(initial=[ row_dict for name, row_dict in auto_get_all_url.items() if name in generate_name_list ]) # 待删除url delete_name_list = permission_set - routes_name_set delete_row_list = [ row_dict for name, row_dict in permission_dict.items() if name in delete_name_list ] # 待更新url if not update_formset: update_name_list = permission_set & routes_name_set update_formset = update_formset_class(initial=[ row_dict for name, row_dict in permission_dict.items() if name in update_name_list ]) return render( request, 'rbac/multi_permission.html', { 'generate_formset': generate_formset, 'delete_row_list': delete_row_list, 'update_formset': update_formset })
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) # 数据库所有URL permissions = models.Permission.objects.all() # 项目路由系统的所有URL router_dict = get_all_url_dict(ignore_namespace_list=[ 'admin', ]) # 数据库所有权限别名 permissions_name_set = set([i.url_name for i in permissions]) # 项目路由系统的所有权限别名 router_name_set = set(router_dict.keys()) # 新增的url别名信息 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 ]) # 更新的url别名信息 update_name_set = permissions_name_set & router_name_set update_formset = FormSet(queryset=models.Permission.objects.filter( url_name__in=update_name_set)) # 删除的url别名信息 del_name_set = permissions_name_set - router_name_set del_formset = FormSet(queryset=models.Permission.objects.filter( url_name__in=del_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) for i in query_list: permissions_name_set.add(i.url_name) # 批量更新 if request.method == 'POST' and post_type == 'update': update_formset = FormSet(request.POST) if update_formset.is_valid(): update_formset = FormSet(queryset=models.Permission.objects.filter( url_name__in=update_name_set)) return render( request, 'multi_permissions.html', { 'del_formset': del_formset, 'update_formset': update_formset, 'add_formset': add_formset, })
def multi_permissions(request): """ 批量操作权限 :param request: :return: """ post_type = request.GET.get('type') # 编辑和删除使用的modelformset FormSet = modelformset_factory(models.Permission, MultiPermissionForm, extra=0) # 新增使用formset AddFormSet = formset_factory(MultiPermissionForm, extra=0) # 从数据库中获取到所有的URL 权限 permissions = models.Permission.objects.all() # 从路由系统中获取到所有的URL { name: { name url } } router_dict = get_all_url_dict(ignore_namespace_list=[ 'admin', ]) # 数据库中权限的url别名的集合 permissions_name_set = set([i.name for i in permissions]) # 路由系统中权限的url别名的集合 router_name_set = set(router_dict.keys()) # 新增权限的别名的集合 add_name_set = router_name_set - permissions_name_set # add_formset = AddFormSet(initial=[ {'url':'sssss','title':'1111'},{'url':'2222','title':'333'}]) 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)) # print(add_formset.errors) return render( request, 'rbac/multi_permissions.html', { 'del_formset': del_formset, 'update_formset': update_formset, 'add_formset': add_formset, })
def post(self, request): post_type = request.GET.get('type') # update(批量更新权限)/generate(批量新增权限) update_formset = None # 批量更新 if post_type == 'update': update_formset_class = formset_factory(MultiEditPermissionForm, extra=0) formset = update_formset_class(data=request.POST) update_formset = formset if formset.is_valid(): post_row_list = formset.cleaned_data for i in range(0, formset.total_form_count()): row_dict = post_row_list[i] permission_id = row_dict.pop('id') try: row_object = models.Permission.objects.filter( id=permission_id).first() for k, v in row_dict.items(): setattr(row_object, k, v) row_object.validate_unique() row_object.save() except Exception as e: print("保存失败") formset.errors[i].update(e) update_formset = formset else: print("formset验证失败") update_formset = formset return render(request, "rbac/multi_permissions.html", { "update_formset": update_formset, }) if post_type == "generate": generate_formset_class = formset_factory(MultiAddPermissionForm, extra=0) formset = generate_formset_class(data=request.POST) generate_formset = formset if formset.is_valid(): object_list = [] post_row_list = formset.cleaned_data has_error = False for i in range(0, formset.total_form_count()): row_dict = post_row_list[i] try: new_object = models.Permission(**row_dict) new_object.validate_unique() object_list.append(new_object) except Exception as e: formset.errors[i].update(e) generate_formset = formset has_error = True if not has_error: models.Permission.objects.bulk_create(object_list, batch_size=100) else: generate_formset = formset return render(request, "rbac/multi_permissions.html", { "generate_formset": generate_formset, })
def multi_permission(request): 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']) """ { 'url别名':{'name':url别名,'url':url}, ... } """ # 数据库中权限的所有的别名 permissions_name_set = set([i.name for i in permissions]) # 路由系统中所有的别名 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) for i in query_list: permissions_name_set.add(i.name) add_formset = AddFormSet() 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_permission.html', { 'del_formset': del_formset, 'update_formset': update_formset, 'add_formset': add_formset, })
def multi_permissions(request): ''' 批量操作权限 :param request: :return: ''' post_type = request.GET.get("type") generate_formset = None update_formset = None update_formset_class = formset_factory(MultiEditPermissionForm, extra=0) generate_formset_class = formset_factory(MultiAddPermissionForm, extra=0) if request.method == "POST" and post_type == "generate": # 批量添加 formset = generate_formset_class(data=request.POST) if formset.is_valid(): has_error = False object_list = [] post_row_list = formset.cleaned_data for i in range(0, formset.total_form_count()): row_dict = post_row_list[i] if not row_dict: continue try: new_object = models.Permission(**row_dict) new_object.validate_unique() object_list.append(new_object) except Exception as e: formset.errors[i].update(e) generate_formset = formset has_error = True if not has_error: models.Permission.objects.bulk_create(object_list, batch_size=100) # 批量添加 else: generate_formset = formset if request.method == "POST" and post_type == "update": # 批量更新 formset = update_formset_class(data=request.POST) if formset.is_valid(): post_row_list = formset.cleaned_data for i in range(0, formset.total_form_count()): row_dict = post_row_list[i] permission_id = row_dict.pop("id") try: row_object = models.Permission.objects.filter( pk=permission_id).first() for k, v in row_dict.items(): setattr(row_object, k, v) row_object.validate_unique() row_object.save() except Exception as e: formset.errors[i].update(e) update_formset = formset else: update_formset = formset # 1.获取项目中,所有的URL all_url_dict = get_all_url_dict() router_name_set = set(all_url_dict.keys()) # 2. 获取数据库中所有的url permissions = models.Permission.objects.all().values( "id", "title", "name", "url", "menu_id", "pid_id") permission_dict = OrderedDict() permission_name_set = set() for row in permissions: permission_dict[row.get("name")] = row permission_name_set.add(row.get("name")) # permission_name_set = set(permission_dict.keys()) # 这个循环主要是为了,进行更新操作的时候。有可能自动发现和数据库中 name 一样而url不一样时。强制更改一下 # 让用户去自己去检查一下。 到底要使用 那个url。 需要用户自己手动填写 for name, value in permission_dict.items(): router_row = all_url_dict.get(name) if not router_row: continue if value.get("url") != router_row.get("url"): value["url"] = "路由和数据库中不一致,请检查。并填写正确的 url!!" # 3. 应该要 添加,删除,修改的权限有哪些 # 3.1 计算出应该添加的name 并生成 formset (自动发现有的,数据库没有的。所以要循环的是 自动发现查询出的字典) if not generate_formset: generate_name_list = router_name_set - permission_name_set # 增加列表 generate_formset = generate_formset_class(initial=[ row_dict for name, row_dict in all_url_dict.items() if name in generate_name_list ]) # 3.2 计算出,应该删除的name,(数据库有的,自动发现 没有的。所以要循环的是 数据库查询出的字典) delete_name_list = permission_name_set - router_name_set # 删除列表 # 页面展示时 不需要删除的formset 只提供一个删除按钮就好 delete_row_list = [ row_dict for name, row_dict in permission_dict.items() if name in delete_name_list ] # 3.3 计算出应该更新的name (数据库有的,自动发现有的。所以要循环的是 数据库查询出的字典) if not update_formset: update_name_list = permission_name_set & router_name_set # 更新列表 update_formset = update_formset_class(initial=[ row_dict for name, row_dict in permission_dict.items() if name in update_name_list ]) return render( request, "rbac/multi_permission.html", { "generate_formset": generate_formset, "delete_row_list": delete_row_list, "update_formset": update_formset }, )
def multi_permissions(request): """ 批量操作权限 :param request: :return: """ post_type = request.GET.get('type') generate_formset_class = formset_factory(MultiAddPermissionForm, extra=0) update_formset_class = formset_factory(MultiEditPermissionForm, extra=0) generate_formset = None update_formset = None if request.method == 'POST' and post_type == 'generate': # 批量添加 formset = generate_formset_class(data=request.POST) if formset.is_valid(): object_list = [] post_row_list = formset.cleaned_data has_error = False for i in range(0, formset.total_form_count()): row_dict = post_row_list[i] try: new_object = models.Permission(**row_dict) new_object.validate_unique() object_list.append(new_object) except Exception as e: formset.errors[i].update(e) generate_formset = formset has_error = True if not has_error: models.Permission.objects.bulk_create(object_list, batch_size=100) else: generate_formset = formset if request.method == 'POST' and post_type == 'update': # pass # 批量更新 formset = update_formset_class(data=request.POST) if formset.is_valid(): post_row_list = formset.cleaned_data for i in range(0, formset.total_form_count()): row_dict = post_row_list[i] permission_id = row_dict.pop('id') try: row_object = models.Permission.objects.filter( id=permission_id).first() for k, v in row_dict.items(): setattr(row_object, k, v) row_object.validate_unique() row_object.save() except Exception as e: formset.errors[i].update(e) update_formset = formset else: update_formset = formset # 1. 获取项目中所有的URL all_url_dict = get_all_url_dict() """ { 'rbac:role_list':{'name': 'rbac:role_list', 'url': '/rbac/role/list/'}, 'rbac:role_add':{'name': 'rbac:role_add', 'url': '/rbac/role/add/'}, .... } """ router_name_set = set(all_url_dict.keys()) # 2. 获取数据库中所有的URL permissions = models.Permission.objects.all().values( 'id', 'title', 'name', 'url', 'menu_id', 'pid_id') permission_dict = OrderedDict() permission_name_set = set() for row in permissions: permission_dict[row['name']] = row permission_name_set.add(row['name']) """ { 'rbac:role_list': {'id':1,'title':'角色列表',name:'rbac:role_list',url.....}, 'rbac:role_add': {'id':1,'title':'添加角色',name:'rbac:role_add',url.....}, ... } """ for name, value in permission_dict.items(): router_row_dict = all_url_dict.get( name) # {'name': 'rbac:role_list', 'url': '/rbac/role/list/'}, if not router_row_dict: continue if value['url'] != router_row_dict['url']: value['url'] = '路由和数据库中不一致' # 3. 应该添加、删除、修改的权限有哪些? # 3.1 计算出应该增加的name if not generate_formset: generate_name_list = router_name_set - permission_name_set generate_formset = generate_formset_class(initial=[ row_dict for name, row_dict in all_url_dict.items() if name in generate_name_list ]) # 3.2 计算出应该删除的name delete_name_list = permission_name_set - router_name_set delete_row_list = [ row_dict for name, row_dict in permission_dict.items() if name in delete_name_list ] # 3.3 计算出应该更新的name if not update_formset: update_name_list = permission_name_set & router_name_set update_formset = update_formset_class(initial=[ row_dict for name, row_dict in permission_dict.items() if name in update_name_list ]) return render( request, 'rbac/multi_permissions.html', { 'generate_formset': generate_formset, 'delete_row_list': delete_row_list, 'update_formset': update_formset, })
def multi_permission(request): """ 批量操作权限视图函数 :param request: :return: """ post_type = request.GET.get('type') increase_formset_class = formset_factory(MultiAddPermissionForm, extra=0) update_formset_class = formset_factory(MultiEditPermissionForm, extra=0) increase_formset = None update_formset = None # 判断请求是否为 POST 请求,且判断提交的数据是否为新增数据提交的内容 if request.method == 'POST' and post_type == 'increase': # 批量添加 formset = increase_formset_class(data=request.POST) if formset.is_valid(): object_list = [] # 创建空列表用于存放需要增加的数据,用来批量增加 post_row_list = formset.cleaned_data has_error = False # 定义一个标记变量,用来确认是否有错误信息 for i in range(0, formset.total_form_count()): row_dict = post_row_list[i] try: new_obj = models.Permission(**row_dict) new_obj.validate_unique() # 对数据进行唯一约束检测 object_list.append(new_obj) except Exception as e: formset.errors[i].update(e) increase_formset = formset has_error = True if not has_error: # 对数据进行批量增加,好过在循环时一条条增加,增加对数据库操作的负担, # batch_size 参数表示每次执行的条数 models.Permission.objects.bulk_create(object_list, batch_size=100) else: increase_formset = formset # 判断请求是否为 POST 请求,且判断提交的数据是否为更新数据操作 if request.method == 'POST' and post_type == 'update': formset = update_formset_class(request.POST) if formset.is_valid(): post_row_list = formset.cleaned_data for i in range(0, formset.total_form_count()): row_dict = post_row_list[i] permission_id = row_dict.pop('pid') try: row_object = models.Permission.objects.filter( pid=permission_id).first() for k, v in row_dict.items(): setattr(row_object, k, v) row_object.validate_unique() row_object.save() except Exception as e: # print(e) formset.errors[i].update(e) update_formset = formset else: update_formset = formset # 第一步获取项目中所有的 URL,并生成一个集合类型的数据 all_url_dict = get_all_url_dict() router_name_set = set(all_url_dict.keys()) # 创建集合 # 第二步获取数据库中所有的 url,并生成一个集合类型的数据 permissions = models.Permission.objects.all().values( 'pid', 'title', 'url_alias', 'url', 'menu_p_id', 'ppid_id') permission_dict = OrderedDict() # 创建有序字典 permission_name_set = set() for row in permissions: permission_dict[row['url_alias']] = row permission_name_set.add(row['url_alias']) # 创建集合,给集合中添加内容语法 # 循环从数据库中取出的 url ,让其与自动获得的 url 进行对比 # 如果两者不一样则交给用户选择用那个作为权限分配的内容 for name, value in permission_dict.items(): # 根据数据库中的 name 从自动获得 url 中进行取值 router_row_dict = all_url_dict.get(name) if not router_row_dict: # 不存在则再次循环 continue # 判断数据库中的 url 与自动获得的 url 是否一致 if value['url'] != router_row_dict['url']: value['url'] = '路由和数据库中的 url 不一致' # 第三步:对项目创建的集合与数据库数据创建的两个集合进行比较, # 用来确定添加、删除、修改的权限有哪些 # 3.1:通过集合运算计算出需要增加的权限 URL 别名,并创建 fromset 设定显示内容 # 判断如果 increase_formset 中没有数据说明此次请求为 get 请求,则使用 form 类生成数据进行渲染 if not increase_formset: increase_name_list = router_name_set - permission_name_set increase_formset = increase_formset_class(initial=[ # 列表生成式取得需要增加的数据 row_dict for name, row_dict in all_url_dict.items() if name in increase_name_list ]) # 3.2:通过集合运算计算出需要删除的权限 URL 别名 delete_name_list = permission_name_set - router_name_set # 需删除的权限 url delete_row_list = [ row_dict for name, row_dict in permission_dict.items() if name in delete_name_list ] # 3.3:通过集合运算计算出需要更新的权限 URL 别名,并创建编辑的 formset if not update_formset: update_name_list = permission_name_set & router_name_set # 求交集需更新的权限 url update_formset = update_formset_class(initial=[ row_dict for name, row_dict in permission_dict.items() if name in update_name_list ]) return render( request, 'rbac/multi_permissions.html', { 'increase_formset': increase_formset, 'delete_row_list': delete_row_list, 'update_formset': update_formset })
def multi_permissions(request): """批量操作权限""" post_type = request.GET.get('type') generate_formset_class = formset_factory(MultiAddPermissionForm, extra=0) update_formset_class = formset_factory(MultiEditPermissionForm, extra=0) # 创建formset类 generate_formset = None update_formset = None # 用户提交区 if request.method == 'POST' and post_type == 'generate': # 批量添加 formset = generate_formset_class(data=request.POST) if formset.is_valid(): # 表单验证 object_list = [] # 先判断有没有唯一索引限制 post_row_list = formset.cleaned_data has_error = False for i in range(0, formset.total_form_count()): row_dict = post_row_list[i] try: new_object = models.Permission(**row_dict) new_object.validate_unique() # 唯一字段判断 object_list.append(new_object) except Exception as e: formset.errors[i].update(e) generate_formset = formset has_error = True if not has_error: # 没有错误就批量增加 models.Permission.objects.bulk_create( object_list, batch_size=100) # 批量增加语法bulk_create else: # 显示错误信息 generate_formset = formset if request.method == 'POST' and post_type == 'update': # 批量更新 formset = update_formset_class(data=request.POST) if formset.is_valid(): post_row_list = formset.cleaned_data for i in range(0, formset.total_form_count()): # 循环总个数 row_dict = post_row_list[i] permission_id = row_dict.pop('id') # 拿到修改页面的id try: row_object = models.Permission.objects.filter( id=permission_id).first() # 数据库已有数据 # 反射 for k, v in row_dict.items(): setattr(row_object, k, v) row_object.validate_unique() # 检测唯一 row_object.save() except Exception as e: formset.errors[i].update(e) update_formset = formset else: update_formset = formset # 展示区 # 1. 取项目中所有URL """ all_url_dict格式 { rbac:role_list {'name': 'rbac:role_list', 'url': '/rbac/role/list/'}, rbac:role_add {'name': 'rbac:role_add', 'url': '/rbac/role/add/'}, ... } """ all_url_dict = get_all_url_dict() router_name_set = set(all_url_dict.keys()) # 设为集合 # 2. 取数据库中所有URL permission = models.Permission.objects.all().values( 'id', 'title', 'name', 'url', 'menu_id', 'pid_id') permission_dict = OrderedDict() permission_name_set = set() # 创建集合 for row in permission: permission_dict[row['name']] = row permission_name_set.add(row['name']) # 放到集合里 """ permission_dict格式 { rbac:role_list {'name': 'rbac:role_list','title':'角色列表', 'url': '/rbac/role/list/'....}, ... } """ # 判断代码中path中和数据库中是否相等(防止万一改到代码后出现bug) for name, value in permission_dict.items(): router_row_dict = all_url_dict.get(name) if not router_row_dict: continue if value['url'] != router_row_dict['url']: value['url'] = '路由和数据库中不一致!' # 3. 拿到两个集合可以进行对比(集合语法),参考 【总】权限分配思路.md # 3.1 计算出应该增加的name '''关于formset的使用可以参考 【https://gitee.com/Zok/formset】 代码库''' if not generate_formset: generate_name_list = router_name_set - permission_name_set # 生成新的 # 制作添加的 formset generate_formset = generate_formset_class(initial=[ row_dict for name, row_dict in all_url_dict.items() if name in generate_name_list ]) # 列表生成式,把应该增加的放到initial中 # 3.2 计算该删除的name delete_name_list = permission_name_set - router_name_set # 删除多的 delete_row_list = [ row_dict for name, row_dict in permission_dict.items() if name in delete_name_list ] # 列表生成式 # 3.3 计算出该更新的name if not update_formset: update_name_list = permission_name_set & router_name_set # 更新(&取交集) # 制作formset (必须要一个隐藏的id字段,才能编辑)在数据库permission中取,因为数据齐全有title,menu_id等 update_formset = update_formset_class(initial=[ row_dict for name, row_dict in permission_dict.items() if name in update_name_list ]) # 列表生成式,把应该增加的放到initial中 return render( request, 'rbac/multi_permissions.html', { 'generate_formset': generate_formset, 'delete_row_list': delete_row_list, 'update_formset': update_formset, })
def multi_permissions(request): """ 批量操作权限 :param request: :return: """ post_type = request.GET.get('type') generate_formset_class = formset_factory(MultiAddPermissionForm, extra=0, ) # extra 是否可以额外添加 generate_formset = None if request.method == 'POST' and post_type == 'generate': # 批量添加 formset = generate_formset_class(data=request.POST) # 获取提交过来的数据 if formset.is_valid(): # 进行验证 object_list = [] post_row_list = formset.cleaned_data # 将数据存一份出来 has_error = False # 是否出错 for i in range(0, formset.total_form_count()): # 循环验证每一行数据,是否在数据库中存在 row_dict = post_row_list[i] print(row_dict) row_dict.pop('pid') print(row_dict) try: new_object = models.Permission(**row_dict) new_object.validate_unique() # 验证是否存在 object_list.append(new_object) # 验证通过, 存到列表中 except Exception as e: formset.errors[i].update(e) # 如有有错误信息,存起来 generate_formset = formset has_error = True if not has_error: # 没有错误的时候,增加 models.Permission.objects.bulk_create(object_list, batch_size=100) # 批量增加数据,减小数据库开销 else: generate_formset = formset update_formset_class = formset_factory(MultiEditPermissionForm, extra=0) # extra 是否可以额外添加 update_formset = None if request.method == 'POST' and post_type == 'update': formset = update_formset_class(data=request.POST) # 获取提交过来的数据 if formset.is_valid(): # 进行验证 print(post_type) post_row_list = formset.cleaned_data # 将数据存一份出来 for i in range(0, formset.total_form_count()): # 循环验证每一行数据,是否在数据库中存在 row_dict = post_row_list[i] print(row_dict) permission_id = row_dict.pop('id') try: row_object = models.Permission.objects.filter(id=permission_id).first() for k, v in row_dict.items(): setattr(row_object, k, v) row_object.validate_unique() # 验证是否存在 row_object.save() # 验证通过, 存到列表中 except Exception as e: formset.errors[i].update(e) # 如有有错误信息,存起来 update_formset = formset else: update_formset = formset all_url_dict = get_all_url_dict() # 1、获取项目中所有的Url的值到一个集合 router_name_set = set(all_url_dict) # 2、获取数据库中所有的url permissions = models.Permission.objects.all().values('id', 'title', 'name', 'url', 'menu_id', 'menu__title', 'pid_id', 'pid__title', 'sort').order_by('name') permission_dict = OrderedDict() # 有序字典 permission_name_set = set() # 集合 for row in permissions: permission_dict[row['name']] = row permission_name_set.add(row['name']) # 3、添加、删除、修改的权限有哪些 # 3.1 计算应该要增加的name # 项目中有 数据库中没有 if not generate_formset: generate_name_list = router_name_set - permission_name_set generate_formset = generate_formset_class( initial=[row_dict for name, row_dict in all_url_dict.items() if name in generate_name_list]) # 3.2 计算应该要删除的name # 数据库中有 项目中没有 delete_name_list = permission_name_set - router_name_set delete_row_list = [row_dict for name, row_dict in permission_dict.items() if name in delete_name_list] # 3.3 应该要更新的name # 3.3.1 先检查一下 项目中的url与数据库中的url是否一样, for name, value in permission_dict.items(): router_row_dict = all_url_dict.get(name) # 数据库中的name 是否存在于项目中 if not router_row_dict: # 如果不存在,不用管,会在要删除里面体现出来 continue if value['url'] != router_row_dict['url']: # 判断数据库中的url与项目中的url的值是否一致 # print(value['url'], router_row_dict['url']) value['url'] = 'url与数据库中的不一致' update_name_list = permission_name_set & router_name_set # 数据库和项目中都有 交集 update_formset = update_formset_class( initial=[row_dict for name, row_dict in permission_dict.items() if name in update_name_list]) return render(request, 'rbac/multi_permissions.html', {'generate_formset': generate_formset, 'delete_row_list': delete_row_list, 'update_formset': update_formset})