首页 > 技术文章 > 第五天.权限批量录入/更新、信号、Django日志配置

dbslinux 2020-05-04 09:16 原文

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

推荐阅读