• CRM——权限


    一、引入权限组件

    1、引入权限组件rbac

      拷贝之前写好的rbac应用到CRM_demo项目下。

      在settings中注册rbac的app:

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'crm.apps.CrmConfig',
        'stark.apps.StarkConfig',
        'rbac.apps.RbacConfig'
    ]
    

      settings中添加rabc中间件:

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'rbac.serive.rbac.ValidPermission'
    ]

    2、员工表Userinfo与rbac.User表做一对一关联

    from rbac.models import *
    
    class UserInfo(models.Model):
        """
        员工表
        """
        name = models.CharField(verbose_name='员工姓名', max_length=16)
        username = models.CharField(verbose_name='用户名', max_length=32)
        password = models.CharField(verbose_name='密码', max_length=64)
        email = models.EmailField(verbose_name='邮箱', max_length=64)
        # 模仿 SQL 约束 ON DELETE CASCADE 的行为,换句话说,删除一个对象时也会删除与它相关联的外键对象。
        depart = models.ForeignKey(verbose_name='部门', to="Department", to_field="code", on_delete=models.CASCADE)
        user = models.OneToOneField(to=User, null=True, on_delete=models.CASCADE)
    
        def __str__(self):
            return self.name
    

      由于是临时添加的字段,因此添加参数null=True。

      然后完成数据迁移:

    manage.py@CRM_demo > makemigrations
    manage.py@CRM_demo > migrate
    

    二、给权限控制配置注册stark

    1、rbac/stark.py

    from stark.service.stark import site,ModelStark
    from .models import *
    
    class UserConfig(ModelStark):
        list_display = ["name", "roles"]
    
    site.register(User, UserConfig)
    
    class RoleConfig(ModelStark):
        list_display = ["title", "permissions"]
    
    site.register(Role, RoleConfig)
    
    class PermissionConfig(ModelStark):
        list_display = ["id", "title", "url", "group", "action"]
    
    site.register(Permission, PermissionConfig)
    site.register(PermissionGroup)
    

    2、添加权限组

      

    3、添加权限

      

      

      注意:

    (1)输入url字段过长

      原来在models.py中配置url的max_length=32这个长度不够输入全部路径,因此将其改为max_length=64。

    (2)编辑操作的url和action

      编辑操作的url取的是crm应用的路径在这里是change,但action取的是rbac的操作分类是edit。

    {% extends 'base.html' %}
    
    {% block con %}
        <h4>角色列表</h4>
        {% if per.add %}
            <a href="/roles/add" class="btn btn-primary">添加角色</a>
        {% endif %}
        <table class="table table-bordered table-striped">
            <tbody>
                {% for role in role_list %}
                    <tr>
                        <td>{{ forloop.counter }}</td>
                        <td>{{ role.title }}</td>
                        <td>
                            {% if per.delete %}
                                <a href="/roles/delete/{{ user.pk }}" class="btn btn-danger">删除</a>
                            {% endif %}
                            {% if per.edit %}
                                <a href="/roles/edit/{{ user.pk }}" class="btn btn-warning">编辑</a>
                            {% endif %}
                        </td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>
    {% endblock %}
    rbac/templates/roles.html

    (3)查看学生成绩添加

       这个是点击学生表对应查看的,不能放在菜单栏中,因此不能将action设为list.

    4、添加角色

      

    5、添加用户

      

    6、给员工分配对应的user

      

      给每个员工分配对应的user:

      

    三、登录、引入中间件

    1、crm_demo/urls.py配置登录url

    from django.contrib import admin
    from django.urls import path
    from django.conf.urls import url
    from stark.service.stark import site
    from crm import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        url(r'^stark/', site.urls),
        url(r'^login/', views.login)
    ]
    

    2、crm/view.py视图配置

    from django.shortcuts import render, HttpResponse
    # Create your views here.
    from rbac.models import User
    from rbac.service.permissions import initial_session
    
    def login(request):
        if request.method == 'POST':
            user = request.POST.get("user")
            pwd = request.POST.get("pwd")
    
            user = User.objects.filter(name=user, pwd=pwd).first()
    
            if user:
                # 登录成功
                request.session["user_id"] = user.pk
                # 注册权限到session中
                initial_session(user, request)
                return HttpResponse("登录成功")
    
        return render(request, "login.html", locals())
    

    3、引入中间件

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'rbac.service.rbac.ValidPermission'
    ]
    

      至此权限控制已经实现了,当不同用户登录时,只能访问具有权限的页面。

    四、页面调整

    1、拷贝base.html及调整

      将rbac应用下的base.html拷贝到CRM_demo项目下的templates里,在这里base.html是首先调用的,可以在不修改rbac组件的情况下调整base.html。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!-- 引入 Bootstrap 核心 CSS 文件 -->
        <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
        <script src="/static/js/jquery-1.12.4.min.js"></script>
        <link rel="stylesheet" href="/static/css/add.css">
        <link rel="stylesheet" href="/static/css/list.css">
        <style>
            .header {
                width: 100%;
                height: 60px;
                background-color: #336699;
            }
    
            .menu {
                background-color: bisque;
                position: fixed;
                top: 60px;
                bottom: 0px;
                left: 0px;
                width: 200px;
            }
    
            .content {
                position: fixed;
                top: 60px;
                bottom: 0;
                right: 0;
                left: 200px;
                overflow: auto; /* 滚动条 */
            }
    
            .menu_btn {
                font-size: 18px;
                text-align: center;
                padding: 30px 0;
            }
        </style>
    </head>
    <body>
    
    <div class="header">
        <p>{{ user.name }}</p>
    </div>
    <div class="contain">
        {% load my_tags %}
        <div class="menu">
            {% get_menu request %}
        </div>
        <div class="content">
            {% block con %}
    
            {% endblock %}
        </div>
    </div>
    </body>
    </html>
    /templates/base.html

      被引入base.html的两个css文件分别是/stark/add_view.html和/stark/list_view.html的css样式。

    input, select {
        display: block;
        width: 100%;
        height: 34px;
        padding: 6px 12px;
        font-size: 14px;
        line-height: 1.42857143;
        color: #555;
        background-color: #fff;
        background-image: none;
        border: 1px solid #ccc;
        border-radius: 4px;
        -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
        box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
        -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
        -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
        transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
    }
    
    .error {
        color: red;
    }
    stark/static/css/add.css
    .filter a {
        text-decoration: none; /* 取消a标签颜色 */
        color: grey;
    }
    
    .active {
        color: red !important; /* 提升优先级 */
    }
    stark/static/css/list.css

    2、模板继承

      此处修改的是stark子应用里的模板。

    (1)add_view.html

    {% extends 'base.html' %}
    
    {% block con %}
        <h3>添加页面</h3>
        {% include 'form.html' %}
        <script>
            function pop(url) {
                window.open(url, "", "width=600, height=400, top=100, left=100")
            }
            function pop_response(pk, text, id) {
                console.log(pk, text, id);   // 10 人民邮电出版社 id_publish
                console.log(typeof text);  // string
                // 选择哪一个select标签
                // option文本值和value值
                var $option = $('<option>');   // 创建标签:<option></option>
                $option.html(text);      // 给标签添加文本:<option>南京出版社</option>
                $option.val(pk);              // 给标签添加value:<option value=111>南京出版社</option>
                $option.attr("selected", "selected");  // 添加属性selected:<option value="111" selected="selected">南京出版社</option>
                $("#" + id).append($option);  // 将标签添加到id="id_publish"的标签中
            }
        </script>
    {% endblock %}
    

    (2)change_view.html

    {% extends 'base.html' %}
    
    {% block con %}
        <h3>编辑页面</h3>
        {% include 'form.html' %}
    {% endblock %}
    

    (3)list_view.html

    {% extends 'base.html' %}
    
    {% block con %}
        <h4>数据列表</h4>
        <div class="container">
            <div class="row">
                <div class="col-md-9">
                    {# <a href="add/" class="btn btn-primary">添加数据</a> #}
                    <a href="{{ add_url }}" class="btn btn-primary">添加数据</a>
                    {% if show_list.config.search_fields %}
                        <form action="" class="pull-right">
                            <input type="text" name="q" value="{{ show_list.config.key_word }}">
                            <button>搜索</button>
                        </form>
                    {% endif %}
                    <form action="" method="post">
                        {% csrf_token %}
                        <select name="action" id="" style=" 200px; padding: 5px 8px; display: inline-block">
                            <option value="">-----------</option>
                            {% for item in show_list.get_action_list %}
                                <option value="{{ item.name }}">{{ item.desc }}</option>
                            {% endfor %}
                        </select>
                        <button type="submit" class="btn-info">Go</button>
                        <table class="table table-bordered table-striped">
                            <thead>
                            <tr>
                                {% for item in header_list %}
                                    <th>{{ item }}</th>
                                {% endfor %}
                            </tr>
                            </thead>
                            <tbody>
                            {% for data in new_data_list %}
                                <tr>
                                    {% for item in data %}
                                        <td>{{ item }}</td>
                                    {% endfor %}
                                </tr>
                            {% endfor %}
    
                            </tbody>
                        </table>
                        <nav>
                            <ul class="pagination">
                                {{ show_list.pagination.page_html|safe }}
                            </ul>
                        </nav>
                    </form>
                </div>
                {% if showlist.config.list_filter %}
                    {# list_filter有值才显示FILTER #}
                    <div class="filter">
                        <h4>Filter</h4>
                        {% for filter_field, linktags in show_list.get_filter_linktags.items %}
                            <div class="well">
                                {# upper方法改为大写 #}
                                <p>{{ filter_field.upper }}</p>
                                {% for link in linktags %}
                                    <p>{{ link|safe }}</p>
                                {% endfor %}
                            </div>
                        {% endfor %}
                    </div>
                {% endif %}
            </div>
        </div>
        <script>
            // 复选框全选
            $("#choice").click(function () {
                if ($(this).prop("checked")) {
                    // 如果是选中状态
                    $(".choice_item").prop("checked", true);
                } else {
                    $(".choice_item").prop("checked", false)
                }
            })
        </script>
    {% endblock %}
    View Code

    (4)public.html

      在CRM_demo项目下的templates里创建。

    {% extends 'base.html' %}
    
    {% block con %}
        <h3>公共客户</h3>
        <div class="container">
            <div class="row">
                <div class="col-md-6">
                    <table class="table table-bordered table-striped">
                        <thead>
                        <tr>
                            <th>ID</th>
                            <th>姓名</th>
                            <th>QQ</th>
                            <th>课程顾问</th>
                            <th>跟进详情</th>
                            <th>确认跟进</th>
                        </tr>
                        </thead>
                        <tbody>
                        {% for customer in customer_list %}
                            <tr>
                                <td>{{ forloop.counter }}</td>
                                <td>{{ customer.name }}</td>
                                <td>{{ customer.qq }}</td>
                                <td>{{ customer.consultant }}</td>
                                <td><a href="/stark/crm/consultrecord/?customer={{ customer.pk }}">跟进记录</a></td>
                                <td><a href="/stark/crm/customer/further/{{ customer.pk }}">确认跟进</a></td>
                            </tr>
                        {% endfor %}
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    {% endblock %}
    View Code

    3、登录后显示效果

      

      侧边菜单都是显示的组的名字:客户管理。

    4、修改显示权限名称

      修改/rbac/service/permissions.py:

    def initial_session(user, request):
        """注册权限到session中"""
    
        # 注册菜单权限
        # permissions = user.roles.all().values("permissions__url", "permissions__group_id", "permissions__action","permissions__group__title").distinct()
        # 在这里将权限组名改为权限名
        permissions = user.roles.all().values("permissions__url", "permissions__group_id", "permissions__action","permissions__title").distinct()
        print("permissions", permissions)
    
        menu_permission_list = []   # 菜单栏中权限列表:空列表
        for item in permissions:
            # item是里面的字典
            if item["permissions__action"] == "list":
                # 列表里面套一个个的元组,每个元组包含url和权限组title
                # menu_permission_list.append((item["permissions__url"], item["permissions__group__title"]))
                # 改为权限名
                menu_permission_list.append((item["permissions__url"], item["permissions__title"]))
    

      登录查看页面:

      

    5、rbac登录问题

      测试中发现一个问题,当想调整权限和角色等信息时,登录/stark/rbac/permission等页面,所有账户都没有访问权限。

      这里必须通过admin组件,添加系统管理员用户和用户组,添加访问、编辑、删除rbac相关页面的权限。

  • 相关阅读:
    laravel扩展xls处理maatwebsite/excel
    php连接ftp
    sublime
    非对称加密
    cron以及在laravel中使用cron
    多任务-python实现-生成器相关(2.1.13)
    多任务-python实现-迭代器相关(2.1.12)
    多任务-python实现-协程(2.1.11)
    多任务-python实现-多进程文件拷贝器(2.1.10)
    多任务-python实现-进程pool(2.1.9)
  • 原文地址:https://www.cnblogs.com/xiugeng/p/9565581.html
Copyright © 2020-2023  润新知