zoukankan      html  css  js  c++  java
  • 第五天.权限批量录入/更新、信号、Django日志配置

    1. 角色、菜单、权限的增删该查
            1. ModelForm增删改查
            2. 增加和编辑使用同一个视图函数
                Form()
                    1. 生成获取用户输入的标签
                    2. 对用户输入的内容做校验
                    3. 保留输入的内容同时展示错误提示信息
                ModelForm()
                    1. 不需要自己写类中字段
                    2. 编辑的时候可以使用instance参数直接把要修改的实例传到form表单
                        1. 生成获取用户输入的标签时能够把instance的属性直接当成默认值
                        2. POST提交的时候可以直接调用save()保存数据
                FormSet()
                    from django.forms import formset_factory
                ModelFormSet()
                    from django.forms import modelformset_factory
                
            
                ORM复习(对象关系映射)
                    1. 对应关系
                        ORM                        数据库
                        类            <-->          数据表
                        属性          <-->           字段
                        对象          <-->          数据行
        2. 爬取icon图标
            1. requests
            2. beautifulsoup4
        
        3. 权限批量录入
            1. 集合的操作
                1. 差集、交集、反交集
            2. 获取一个Django项目的所有路由
                rbac/utils/reload_routes.py
            3. 页面上将没有入库的路由数据直接加载到addformset中
            4. formset使用的三个要点
                1. {{ formsetobj.management_form }}      --> 管理form(提交数据的时候告诉后端我提交了多少条数据)
                2. 每一条数据中都要有form_obj.id(添加的时候不需要,编辑的时候需要)
                3. form表单的那三要素
    2. 今日内容
     权限的批量操作
            项目复杂之后URL有很多
            1. 自动根据项目的URL录入路由信息(能自动获取路由别名和URL)
                1. Django中的路由
                    二级路由 --> rbac:menu_list  #:号就是分割命名空间的,也就是rbacapp的urls.py中还可以再include包另外的路由
                    三级路由 --> rbac:menu:menu_list
            2. 自动录入写完之后会有三种情况:
                1. 权限表里有,项目里面没有
                2. 权限表里有,项目里面也有
                3. 权限表里没有,项目里面有--如加新功能app
        
            3. formset提交数据三要素
                1. form表单
                2. submit按钮
                3. formset_obj.management_form
            4. 因为使用的是Formset而不是ModelFormset所以不能调用save()保存,需要自己手动创建数据
    1. 批量录入权限2 1. formset和modelformset的使用 2. 集合的操作 3. 如何巧妙的区分同一个action两次不同的POST请求 2. jQuery中文文档:http://jquery.cuishifeng.cn/ 3. 批量更新权限 1. 页面实现 1. Bootstrap、jQuery 2. 页面更新 1. 两个form表单POST提交数据 永远都唔好低估自己! 不负此生,前程似锦!

    一.批量录入权限

      我想实现的是利用formset实现的是只要你访问某个url,就能把当前项目里所有的路由:第一部分项目里没有但权限表里没有的放在下图1新增中。第二部分是我权限表和项目里都有的,放在下图2更新权限中。第三部分是我数据库里有但项目里没有的,放在如下图3中,此三图在一个页面实现操作管理。

       

     

     (1)rbac/utils/reload_routes.py:自动录入脚本

    from django.conf import settings
    from django.utils.module_loading import import_string #module_loading是加载模块
    from django.urls import RegexURLResolver
    from collections import OrderedDict
    
    #per_namespae是前一个命名空间,pre_url是上一级路由,urlpatterns路由表达式,生成一字典
    def recursion_urls(pre_namespace, pre_url, urlpatterns, url_ordered_dict):
        for item in urlpatterns:
            # 如果是嵌套的URL
            if isinstance(item, RegexURLResolver):
                if pre_namespace:
                    if item.namespace:
                    #如果是嵌套的路由那就拿上一级路由命名空间给它拼起来,如果没有上一级则不用拼接直接赋值
                        namespace = '{}:{}'.format(pre_namespace, item.namespace,)
                    else:
                        namespace = pre_namespace
                else:
                    if item.namespace:
                        namespace = item.namespace
                    else:
                        namespace = None
                # 如果还有嵌套的三级、四级...路由就递归的执行
                recursion_urls(namespace, pre_url + item.regex.pattern, item.url_patterns, url_ordered_dict)
            # 普通URL
            else:
                if pre_namespace:
                    name = '{}:{}'.format(pre_namespace, item.name,)
                else:
                    name = item.name
                if not item.name:
                    raise Exception('URL路由中必须设置name属性')
                url = pre_url + item.regex.pattern
                # 把分析出来的每一条路由都以 命名空间:路由别名 为key 存到有序字典里
                url_ordered_dict[name] = {'name': name, 'url': url.replace('^', '').replace('$', '')}
    
    
    def get_all_url_dict(ignore_namespace_list=None):#忽略命名空间的列表作为参数但它是可变类型所以设为none好
        """获取路由中"""
        ignore_list = ignore_namespace_list or []
        # 生成一个有序的字典
        url_ordered_dict = OrderedDict()
        # 导入Django的路由配置:import_string是根据一字符串导入的模块
        root_url_conf = import_string(settings.ROOT_URLCONF)
        # 生成一个空列表
        urlpatterns = []
        # for循环项目所有的路由--luffy_permission/urls.py中的所有路由列表--一级路由
        for item in root_url_conf.urlpatterns:
            #如果路由是regexurlresolver嵌套路由类型且命名空间在忽略的列表中就continue跳过这次循环
            if isinstance(item, RegexURLResolver) and item.namespace in ignore_list:
                continue
            urlpatterns.append(item)
        # 调用上方的函数分析并收集项目中的路由,None是pre_namespace参数(前一个命名空间--在django的路由里它可以嵌套好几层)
        recursion_urls(None, '/', urlpatterns, url_ordered_dict)
        return url_ordered_dict

    (2)rbac/urls.py中:

    #权限批量录入
    url(r'^permission_entry/$', views.permission_entry, name='permission_entry'),

    (3)rbac/views.py中:

    from rbac.utils import permission ,reload_routes
    from rbac.forms import RoleForm, MenuForm, PermissionForm
    from django.forms import modelform_factory, formset_factory
    
    # 权限录入
    def permission_entry(request):
        # 项目里面所有的路由--当你一访问permission_entry时调用get_all_dict方法
        all_urls = reload_routes.get_all_url_dict(ignore_namespace_list=['admin', ])
        # 数据库中权限表中存储的所有路由
        all_permissions = Permission.objects.all()
    
        # 用集合去判断
        # 项目中所有路由的集合
        project_url_set = set(all_urls.keys())
        # 数据库中permission表中的路由集合
        db_url_set = set([i.name for i in all_permissions])
        # 项目中有,数据库中没有
        only_in_project = project_url_set - db_url_set
        # 这些路由应该是等待添加到数据库中权限表里面的数据
        AddFormset = formset_factory(PermissionForm, extra=0)
        add_formset_obj = AddFormset(initial=[v for k, v in all_urls.items() if k in only_in_project])
        if request.method == 'POST':
            add_formset_obj = AddFormset(request.POST)
            if add_formset_obj.is_valid():
                # 手动创建permission
                objs = (Permission(**item) for item in add_formset_obj.cleaned_data)
                Permission.objects.bulk_create(objs)
                return redirect(reverse('rbac:permission_entry'))
        return render(
            request,
            'rbac/permission_entry.html',
            {'add_formset_obj': add_formset_obj}
        )

    (4)rbac/templates/rbac/permission_entry.html中:

      放三个小面板.

    {% extends 'layout.html' %}
    
    {% block content %}
        <div class="container-fluid">
            <div class="row">
                <div class="col-md-12">
                    <form action="" method="post">
                    {% csrf_token %}
                        <div class="panel panel-default">
                        <div class="panel-heading">
                            <h3 class="panel-title">添加权限
                            <button class="btn btn-success btn-xs pull-right" type="submit">添加</button>
                            </h3>
                        </div>
                        <div class="panel-body">
                            <p>那些只在项目中,还没来得及太能加到permission表中的路由数据</p>
                            <table class="table table-bordered">
                                <thead>
                                <tr>
                                    <th>#</th>
                                    <th>title</th>
                                    <th>url</th>
                                    <th>show</th>
                                    <th>name</th>
                                    <th>menu</th>
                                </tr>
                                </thead>
                                <tbody>
                                {% for form_obj in add_formset_obj %}
                                    {{ add_formset_obj.management_form }}
                                    <tr>
                                        {{ form_obj.id }}
                                        <td>{{ forloop.counter }}</td>
                                        <td>{{ form_obj.title }} <span>{{ form_obj.title.errors.0 }}</span></td>
                                        <td>{{ form_obj.url }}</td>
                                        <td>{{ form_obj.show }}</td>
                                        <td>{{ form_obj.name }}</td>
                                        <td>{{ form_obj.menu }}</td>
                                    </tr>
                                {% endfor %}
    
                                </tbody>
                            </table>
                        </div>
                    </div>
                    </form>
                </div>
            </div>
        </div>
    {% endblock %}

    3

  • 相关阅读:
    Excel中的日期时间计算,套路很全
    WPS表格 制作甘特图
    关于海康威视与Unity3d集成冲突问题解决
    海康威视(iOS集成)
    Objective-C
    Android中windowTranslucentStatus与windowTranslucentNavigation的一些设置(转)
    Could not symlink include/node/android-ifaddrs.h
    dyld`__abort_with_payload:
    about the libiconv.2.dylib
    Intent的作用和表现形式简单介绍
  • 原文地址:https://www.cnblogs.com/dbslinux/p/12825321.html
Copyright © 2011-2022 走看看