使用Django Admin,所有用户登录后的页面都是一堆表,现在想做成自己想要的样式,如不同的人登录,根据权限,显示不同的菜单项和不同的首页。
根据不同的人,渲染不同的内容。
一、下载一个网站的模板,bootstrap-4.6.1-examples中的dashboard
共三个文件:
将index.html拷贝到templates目录下
在/static目录下创建css、js子目录,将需要的css、js文件拷贝进去,通过index.html分析,主要涉及以下文件 :上图的dashboard.css和dashboard.js,这是模板的样式文件和js文件,还需要一些支持文件,bootstrap.min.css、bootstrap.bundle.min.js、bootstrap.min.js、chart.min.js、feather.js等。
二、建立应用单独的urls:
在项目的urls中增加:path('plcrm',include("plcrm.urls")),
在应用下建立urls.py:
from django.urls import path
from plcrm import views
urlpatterns = [
path('/', views.index),
]
建立根页面路径,即访问http://127.0.0.1/plcrm/访问的页面
删除一些菜单和数据:
三、登录显示,将Sign out处用{{request.user}}代替,因为使用的是Django admin,admin登录了,这里的request.user就是登录的用户。当我们用root登录时,这里显示的就是root。
四、实现登录后的权限跟随,即不同人员登录,显示不同的菜单项:
这是一个用户、角色、菜单项的联动操作。
1、首先登录使用的是User中维护的用户,这是admin的登录用户表,我们是借助admin的登录功能。这个表与我们自定义的UserProfile表关联,我们实际的用户名在UserProfile表的name中,所以上面的登录显示用户最好是写成{{ request.user.userprofile.name }},这样就显示我们录入的名字。
2、UserProfile表又跟Roles表关联,也就是UserProfile表中保存了对应用户的角色,当然,一个用户可以有多个角色。
3、Roles角色表又跟菜单项表Menus关联,即一个角色可以访问哪些菜单项。
4、最后是单独的菜单项表,维护着不同的菜单项。
在维护上要从后向前维护
1、先定义不同的菜单项:
一共增加了3个:
名字就是在前端页面显示的菜单项的名称,自己根据实际情况任意编写的,重点是这里的url_name,这是在urls.py中定义的:
实际上就是路由项的别名,根据这个名字,在前端就能生成资源的url,在后端就能找到对应的视图函数。
2、维护角色,对不同角色赋予不同的菜单项,也就是赋予不同的权限
如定义一个超级管理员:三个菜单项都能访问到
3、维护用户,先维护admin的User用户,即维护登录用户,定义了三个用户
然后维护我们自己定义的UserProfile用户表
这样,超级用户拥有超级管理员角色,可以访问全部三个资源,销售人员拥有销售角色,可以访问销售和客户两个资源,学生王一拥有学生角色,只能访问学生资源。
4、针对URL,编写视图函数:
from django.shortcuts import render
# Create your views here.
def index(req):
return render(req,"index.html")
def student_index(req):
return render(req,"student/student_index.html")
def cust_index(req):
return render(req,"cust/cust_index.html")
前端:base.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
<meta name="generator" content="Hugo 0.88.1">
<title>自定制 Dashboard Template · Bootstrap v4.6</title>
<!-- Bootstrap core CSS -->
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
<style>
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
</style>
<!-- Custom styles for this template -->
<link href="/static/css/dashboard.css" rel="stylesheet">
</head>
{% block mybody %}
{% endblock %}
</html>
index.html
{% extends "base.html" %}
{% block mybody %}
<body>
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
<a class="navbar-brand col-md-3 col-lg-2 mr-0 px-3" href="#">我的客户管理系统</a>
<button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-toggle="collapse" data-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<!-- input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search" -->
<ul class="navbar-nav px-3">
<li class="nav-item text-nowrap">
<a class="nav-link" href="#">{{ request.user.userprofile.name }}</a>
</li>
</ul>
</nav>
<div class="container-fluid">
<div class="row">
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
<div class="sidebar-sticky pt-3">
<ul class="nav flex-column">
{% for role in request.user.userprofile.roles.all %}
{% for menu in role.menus.all %}
<li class="nav-item">
<a class="nav-link active" href="{% url menu.url_name %}">
<span data-feather="home"></span>
{{ menu.name }} <span class="sr-only">(current)</span>
</a>
</li>
{% endfor %}
{% endfor %}
</ul>
</div>
</nav>
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4">
{% block page-content %}
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Dashboard</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<div class="btn-group mr-2">
<button type="button" class="btn btn-sm btn-outline-secondary">Share</button>
<button type="button" class="btn btn-sm btn-outline-secondary">Export</button>
</div>
<button type="button" class="btn btn-sm btn-outline-secondary dropdown-toggle">
<span data-feather="calendar"></span>
This week
</button>
</div>
</div>
<canvas class="my-4 w-100" id="myChart" width="900" height="380"></canvas>
<h2>Section title</h2>
<div class="table-responsive">
</div>
{% endblock %}
</main>
</div>
</div>
<script src="/static/js/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="/static/js/jquery.slim.min.js"><\/script>')</script><script src="/static/js/bootstrap.bundle.min.js"></script>
<script src="/static/js/feather.4.28.min.js"></script>
<script src="/static/js/Chart.2.9.4.min.js"></script>
<script src="/static/js/dashboard.js"></script>
</body>
{% endblock %}
这个前端页面中,主要注意for循环的写法,request.user.userprofile.roles.all是获取用户全部角色,使用admin的用户系统,前端就能获得用户信息,即request.user,又根据关联性,可以依次找到userprofile和roles,最终获得此用户的全部角色。然后再遍历每个角色的menu,即找到菜单项,显示出来。
cust_index.html
{% extends "index.html" %}
{% block page-content %}
客户首页
{% endblock %}
student_index.html
{% extends "index.html" %}
{% block page-content %}
学生页面首页
{% endblock %}
当以root登录时:
以user01登录时:
以user02登录:
以上就实现了用户、角色、权限的联动。
存在的问题:
两个角色如果有相同的菜单项,并且这两个角色被赋给同一用户,菜单显示会重复;
在地址栏中直接输入资源url,也能访问页面上不存在的菜单项。
五、实现表的展现
类似DjangoAdmin中一个表的展现方式。要做成通用的,所以单独做成一个APP,即单独一个应用。
添加新的APP,第一种方法在pycharm中找到tools——>run manage.py task...,然后在窗口中直接输入startapp appname
第二种方法是在终端运行:python manage.py startapp appname
创建后,需要在settings中增加app名称:
看pycharm自动创建的APP,其增加的是 'appname.apps.PlcrmConfig',,但在网上看到很多都是直接写appname,这里用'appname.apps.PlcrmConfig'试试。