zoukankan      html  css  js  c++  java
  • 批量操作权限的页面展示

    进行展示的时候, 肯定是通过formset 来完成这项工作。
    1. 获取项目中所有的,想要的权限。 比如保存在一个集合中。 set1
    2. 获取数据库中,已经录入了的所有权限。 保存在另一个集合中。 set2

    下面 就出现了三种情况:(这里还是需要通过name字段,来进行 判断。 两个集合)
      情况一: set1 比 set2  多。  说明就要把 多出来的 添加到数据库。 批量添加
      情况二: set1 比 set2 少。说明中途可能弃用了一部分url。 数据库就要删除这部分。  批量删除。
      情况三: set1 和 set2 一样多。 但是可能url 改变了。 所以就需要将 set1 中查出的 与 set2 中中查出的, name一样。 url 不一样的,进行批量更新。

    OK  大概也就这三种情况:  一个一个的实现:
    1.  我已经从项目中获取了,所有的url。 还需要把数据库中,保存着的 permission 的所有信息全部拿到。

        permissions = models.Permission.objects.all().values("pk", "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"))

    在这里也是使用的  OerderdDict  有序字典。
    然后放入到了一个  集合当中。 这个集合只放了   每一条记录中的  name 字段的。 信息。
    看看什么样:

    permission_name_set
    {'role_edit', 'customer_edit', 'payment_add', 'payment_list', 'payment_del', 'second_menu_del', 'role_list', 'menu_list',
    'menu_del', 'customer_del', 'user_list', 'customer_import', 'user_add', 'user_del', 'permission_edit', 'permission_add',
    'customer_tpl', 'reset_pwd', 'second_menu_add', 'menu_add', 'customer_list', 'menu_edit', 'user_edit', 'payment_edit',
    'second_menu_edit', 'permission_del', 'customer_add', 'role_add', 'role_del'}

    自动获取, 得到的也是一个字典。  也需要将每一个 字典的key 保存到一个集合当中:

    all_url_dict = get_all_url_dict()
    router_name_set = set(all_url_dict.keys())
    router_name_set
    {'role_edit', 'customer_edit', 'payment_add', 'multi_permissions', 'payment_list', 'payment_del', 'second_menu_del', 'role_list',
    'menu_list', 'menu_del', 'customer_del', 'user_list', 'customer_import', 'user_add', 'user_del', 'permission_edit',
    'permission_add', 'customer_tpl', 'reset_pwd', 'second_menu_add', 'menu_add', 'customer_list', 'menu_edit', 'user_edit',
    'payment_edit', 'second_menu_edit', 'permission_del', 'customer_add', 'role_add', 'role_del'}

    两个集合有了: 该做差集 并集 操作了!
    情况一。 批量添加操作: 自动获取中有的, 数据库没有的, 需要进行添加到数据库:

        # 3.1 计算出应该添加的name 并生成 formset (自动发现有的,数据库没有的。所以要循环的是 自动发现查询出的字典)
        generate_name_list = router_name_set - permission_name_set  # 增加列表
        generate_formset_class = formset_factory(MultiAddPermissionForm, extra=0)
        generate_formset = generate_formset_class(
            initial=[row_dict for name, row_dict in all_url_dict.items() if name in generate_name_list])

    这里有关 formset的操作,不再说: 前面的博客中有提到,(忘了就去复习)
    这段代码做的事情就是  将每一个 row_dict 中我保存的  name 和 url 交给了  MultiAddPermissionForm 类里面定义的 name 和 url。
    title  肯定是空的。 因为这需要, 用户自己起名字吗嘛!

    情况二: 批量删除操作:自动获取中没有的, 数据库有的, 需要从数据库删除掉:

    (数据库有的,自动发现 没有的。所以要循环的是 数据库查询出的字典) 
    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]

    删除操作, 就不涉及任何修改了。 直接使用一个列表, 前端循环列表然后,进行渲染就行了!

    情况三: 批量更新操作: 自动获取中有的, 数据库有的。

        for name, value in permission_dict.items():
            router_row = all_url_dict.get(name)  # 从all_url_dict取出key为 name 的值
            if not router_row:  # 如果没有找到,直接跳过。
                continue
            if value.get("url") != router_row.get("url"):  # 找到的情况下, 比对 两个的 url 是否一直
                value["url"] = "路由和数据库中不一致,请检查。并填写正确的  url!!"
    
        # 3.3 计算出应该更新的name (数据库有的,自动发现有的。所以要循环的是 数据库查询出的字典)
        update_name_list = permission_name_set & router_name_set  # 更新列表
        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])

    这里先一步对两个 字典中的数据进行了比较。 因为有可能会有  name 是一样的,但是 url 不一样的情况。
    那就需要  对 用户有个提示。 所以做了个循环的判断。 发现url 不相等的情况时, 就将这个url 给修改成一个 提示字符串。然后让用户自己去检查,要使用
    那个url  然后填写正确的 url  进行保存。

     最后就是, 前端页面的渲染,然后让用户进行操作完成之后的保存了!

    不论是 添加还是 更新, 都需要一个 form 标签。来进行数据的传递。 action="" 表示。默认使用当前页面的 url 进行数据发送。
    为了分清,我这次提交的数据, 是添加的, 还是更新的。 我改变了一下action。

    <form method="post" action="?type=generate">
        ......
    </form>
    
    <form method="post" action="?type=update">
        ......
    </form>
    post_type = request.GET.get("type") 判断GET 中取到的是generate 或者 update  来判断这次的数据,是用于添加或者更新
    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 = []  # 添加时 将每一个model对象 添加到  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)  # 将字典交给Permission模型。得到model对象
                        new_object.validate_unique()  # 判断与数据库中  有限制unique的字段,是否重复。  如果有抛出异常
                        object_list.append(new_object)  # 无异常的 添加到列表中
                    except Exception as e:
                        formset.errors[i].update(e)  #  捕获错误, 并将错误信息,添加到当前form对象的error字典中。
                        generate_formset = formset  # 将接收用户数据之后的 formset 重新赋值给generate_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) # model对象也是一个 类 实例化来的。 所以使用反射 进行赋值操作 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_del(request, pk): ''' 删除操作, 需要给与用户提示。 :param reuqest: :param pk: 要删除的权限id :return: ''' origin_url = memory_reverse(request, "rbac:multi_permissions") permission_queryset = models.Permission.objects.filter(pk=pk) if not permission_queryset: return HttpResponse("菜单不存在") if request.method == "POST": permission_queryset.delete() return redirect(origin_url) return render(request, "rbac/delete.html", {"cancel": origin_url})

    批量就做好了, 至于想让,那个权限属于谁。 看实际情况进行。 自行选择。
    无法进行,程序的强制限制。 太麻烦

  • 相关阅读:
    Bootstrap的模态框中使用kindeditor无法编辑的问题
    resource is out of sync withthe file system
    Model报错:指定的存储区提供程序在配置中找不到 的解决
    两极——关于未来云计算的瞎想
    c#动态加载dll并调用dll中类的方法
    委托与事件的IL简单分析
    php搭建与网页服务器故障排查
    某AOP文章的注解……关于上下文和remoting
    终于有了我的blog了
    使用C#编写JavaScript
  • 原文地址:https://www.cnblogs.com/chengege/p/10723314.html
Copyright © 2011-2022 走看看