首先,我们必须明确,在这四种角色登录网站,看到页面是不同,这里不仅涉及到后端的权限控制,还涉及到前端页面的布局,区分好这些角色看的东西哪些是相同的,哪些又是不同的呢,这个必须在这里想明白,所以要做好页面布局

  页面布局,去到bootstrap中文网,寻找适合自己的布局实例,然后右击保存页面下载代码,copy代码到自己的项目,然后删删改改,当然完全可以自己用boottrap进行页面布局也是可以的,主要看你是否要求对前端精深,时刻明确自己的目的,学会借力打力,这样做才有效率,否则事事亲力亲为,尤其是在技术更新迭代如此快的时代,难免会让自己陷入一种不进则退的尴尬境地,把自己定位为一个代码整合者或者是技术整合者,也是一个不失水准的定位,所以我们在这个项目中,直接copy实例代码,封面如下:

  目录架构

  在目录架构上,主要是模板渲染和静态文件分类,至于静态文件分类呢,之前图片和css和js什么的,就不用多说了,主要是plugins,放啥呢,放一些前端插件,另外一个就是模板渲染了,为了更好的管理前端代码,肯定是要用到母版继承的,其中base.html主要放一些连接css文件和js文件的静态数据,而其body部分由子版index.html继承,而继承index.html也只定义为页面公用功能部分(菜单)

<!DOCTYPE html>
<html lang="zh-CN"><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<meta name="description" content="">
<meta name="author" content="">
<!--<link rel="icon" href="https://v3.bootcss.com/favicon.ico">--> <title>Perfect CRM</title> <!-- Bootstrap core CSS -->
<link href="/static/css/bootstrap.css" rel="stylesheet"> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<link href="/static/css/ie10-viewport-bug-workaround.css" rel="stylesheet"> <!-- Custom styles for this template -->
<link href="/static/css/dashboard.css" rel="stylesheet"> <!-- Just for debugging purposes. Don't actually copy these 2 lines! -->
<!--[if lt IE 9]><script src="/static/js/ie8-responsive-file-warning.js"></script><![endif]-->
<script src="/static/js/ie-emulation-modes-warning.js"></script> </head> {% block body %}
{% endblock %} <!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="/static/js/jquery.js"></script>
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="/static/js/bootstrap.js"></script>
<!-- Just to make our placeholder images work. Don't actually copy the next line! -->
<script src="/static/js/holder.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="/static/js/ie10-viewport-bug-workaround.js"></script> </html>

base.html

{% extends 'base.html '%}

{% block body %}
<body> <nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Dashboard</a></li>
<li><a href="#">Settings</a></li>
<li><a href="#">Profile</a></li>
<li><a href="#">Help</a></li>
</ul>
<form class="navbar-form navbar-right">
<input class="form-control" placeholder="Search..." type="text">
</form>
</div>
</div>
</nav> <div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav nav-sidebar">
<li class="active"><a href="#">Overview <span class="sr-only">(current)</span></a></li>
<li><a href="#">Reports</a></li>
<li><a href="#">Analytics</a></li>
<li><a href="#">Export</a></li>
</ul>
<ul class="nav nav-sidebar">
<li><a href="">Nav item</a></li>
<li><a href="">Nav item again</a></li>
<li><a href="">One more nav</a></li>
<li><a href="">Another nav item</a></li>
<li><a href="">More navigation</a></li>
</ul>
<ul class="nav nav-sidebar">
<li><a href="">Nav item again</a></li>
<li><a href="">One more nav</a></li>
<li><a href="">Another nav item</a></li>
</ul>
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<h1 class="page-header">Dashboard</h1> <div class="row placeholders">
<div class="col-xs-6 col-sm-3 placeholder">
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" class="img-responsive" alt="Generic placeholder thumbnail" width="" height="">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
<div class="col-xs-6 col-sm-3 placeholder">
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" class="img-responsive" alt="Generic placeholder thumbnail" width="" height="">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
<div class="col-xs-6 col-sm-3 placeholder">
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" class="img-responsive" alt="Generic placeholder thumbnail" width="" height="">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
<div class="col-xs-6 col-sm-3 placeholder">
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" class="img-responsive" alt="Generic placeholder thumbnail" width="" height="">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
</div> <h2 class="sub-header">Section title</h2>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Header</th>
<th>Header</th>
<th>Header</th>
<th>Header</th>
</tr>
</thead>
<tbody>
<tr>
<td>1,001</td>
<td>Lorem</td>
<td>ipsum</td>
<td>dolor</td>
<td>sit</td>
</tr>
<tr>
<td>1,002</td>
<td>amet</td>
<td>consectetur</td>
<td>adipiscing</td>
<td>elit</td>
</tr>
<tr>
<td>1,003</td>
<td>Integer</td>
<td>nec</td>
<td>odio</td>
<td>Praesent</td>
</tr>
<tr>
<td>1,003</td>
<td>libero</td>
<td>Sed</td>
<td>cursus</td>
<td>ante</td>
</tr>
<tr>
<td>1,004</td>
<td>dapibus</td>
<td>diam</td>
<td>Sed</td>
<td>nisi</td>
</tr>
<tr>
<td>1,005</td>
<td>Nulla</td>
<td>quis</td>
<td>sem</td>
<td>at</td>
</tr>
<tr>
<td>1,006</td>
<td>nibh</td>
<td>elementum</td>
<td>imperdiet</td>
<td>Duis</td>
</tr>
<tr>
<td>1,007</td>
<td>sagittis</td>
<td>ipsum</td>
<td>Praesent</td>
<td>mauris</td>
</tr>
<tr>
<td>1,008</td>
<td>Fusce</td>
<td>nec</td>
<td>tellus</td>
<td>sed</td>
</tr>
<tr>
<td>1,009</td>
<td>augue</td>
<td>semper</td>
<td>porta</td>
<td>Mauris</td>
</tr>
<tr>
<td>1,010</td>
<td>massa</td>
<td>Vestibulum</td>
<td>lacinia</td>
<td>arcu</td>
</tr>
<tr>
<td>1,011</td>
<td>eget</td>
<td>nulla</td>
<td>Class</td>
<td>aptent</td>
</tr>
<tr>
<td>1,012</td>
<td>taciti</td>
<td>sociosqu</td>
<td>ad</td>
<td>litora</td>
</tr>
<tr>
<td>1,013</td>
<td>torquent</td>
<td>per</td>
<td>conubia</td>
<td>nostra</td>
</tr>
<tr>
<td>1,014</td>
<td>per</td>
<td>inceptos</td>
<td>himenaeos</td>
<td>Curabitur</td>
</tr>
<tr>
<td>1,015</td>
<td>sodales</td>
<td>ligula</td>
<td>in</td>
<td>libero</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div> </body>
{% endblock %}

index.html

from django.conf.urls import url,include
from django.contrib import admin urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^crm/', include('app01.urls')),
# url(r'^test/', views.test),
]

PerfectCRM urls.py

  动态菜单

  要想实现不同角色用户看到菜单项是不一样的,那这里就要实现动态菜单了,那你怎么让它动起来呢,要想知道这个问题的答案,你就必须想清楚这个问题:依据什么动?角色?这个没错,但是你要想登录网站的是角色吗?不是吧,是用户,对,就是用户,用户再绑定某些角色,所以这里我们要依据用户来动,那怎么动呢?首先,我们要获取用户相关信息,然后返回前端,这里就涉及到模板渲染还是js加载,首次页面加载,并且还是页面公共部分,当然首选模板渲染了,另外每个角色加载哪些菜单项,也需要在某个地方进行定义,就在内存了,还是在数据库了?考虑易扩展性以及角色和菜单项之间是多对多的关系,在这里我们就数据库存储菜单关系,所以我们还要增加一张菜单表

class Role(models.Model):
'''角色表'''
name = models.CharField(max_length=32, unique=True)
menus = models.ManyToManyField('Menu',blank=True)
def __unicode__(self):
return self.name class Meta:
verbose_name_plural = "角色表" class Menu(models.Model):
'''菜单'''
name = models.CharField(max_length=32)
url_name = models.CharField(max_length=64) #request url 有别名存别名 没有就存url def __unicode__(self):
return self.name class Meta:
verbose_name_plural = '菜单表'

   动态路由设计好,那接下来就是把它显示到前端了,你会怎么做了?当然是通过后端ORM查询到用户可以有的菜单项,传到前端,然后通过模板语言for循环渲染就可以了。嗯!这样做没错,你忽略一些小细节,这里还可以更简洁一点--直接在前端查询数据并for循环!你可能有些懵逼了,我们来看是怎么回事?还记得定义用户表时,我们的user字段是直接一对一关联到django自带认证系统的一张表吗?

class UserProfile(models.Model):
'''账号表'''
user = models.OneToOneField(User)
name = models.CharField(max_length=32)
roles = models.ManyToManyField('Role', blank=True, null=True) def __unicode__(self):
return self.name class Meta:
verbose_name_plural = "账号表"

  django是把request直接嵌在了模板里,而request.user指的就是django自带的这张表,就直接在前端调用{{ request.user }},则显示用户名;既然能在前端调用django自带表,那我们就可以用这张表查询所有的有关用户的信息了,由它查userprofile表是反向查询,一对一反向查询是  表.反向表名(小写).字段,也就是request.user.userprofile.roles,你看就是这么简单

           {% for role in request.user.userprofile.roles.all %}
{% for menu in role.menus.all %}
<li class="active"><a href="{% url menu.url_name %}">{{ menu.name }}<span class="sr-only">(current)</span></a></li>
{% endfor %}
{% endfor %}
{% extends 'base.html '%}

{% block body %}
<body> <nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Perfect CRM</a>
</div> <!--显示登录用户栏-->
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<!--留一个显示用户名-->
<li><a href="#">{{ request.user }}</a></li>
</ul>
</div>
</div>
</nav> <div class="container-fluid">
<div class="row"> <!--左侧栏-->
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav nav-sidebar">
{% for role in request.user.userprofile.roles.all %}
{% for menu in role.menus.all %}
<li class="active"><a href="{% url menu.url_name %}">{{ menu.name }}<span class="sr-only">(current)</span></a></li>
{% endfor %}
{% endfor %}
</ul>
</div> <!--接下来是内容区--> <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<!--内容圆饼图区--> {% block page-content %}
<h1 class="page-header">Dashboard</h1> <div class="row placeholders">
<div class="col-xs-6 col-sm-3 placeholder">
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" class="img-responsive" alt="Generic placeholder thumbnail" width="" height="">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
<div class="col-xs-6 col-sm-3 placeholder">
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" class="img-responsive" alt="Generic placeholder thumbnail" width="" height="">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
<div class="col-xs-6 col-sm-3 placeholder">
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" class="img-responsive" alt="Generic placeholder thumbnail" width="" height="">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
<div class="col-xs-6 col-sm-3 placeholder">
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" class="img-responsive" alt="Generic placeholder thumbnail" width="" height="">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
</div> <!--内容详细数据-->
<h2 class="sub-header">Section title</h2>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Header</th>
<th>Header</th>
<th>Header</th>
<th>Header</th>
</tr>
</thead>
<tbody>
<tr>
<td>1,001</td>
<td>Lorem</td>
<td>ipsum</td>
<td>dolor</td>
<td>sit</td>
</tr>
<tr>
<td>1,002</td>
<td>amet</td>
<td>consectetur</td>
<td>adipiscing</td>
<td>elit</td>
</tr>
<tr>
<td>1,003</td>
<td>Integer</td>
<td>nec</td>
<td>odio</td>
<td>Praesent</td>
</tr>
<tr>
<td>1,003</td>
<td>libero</td>
<td>Sed</td>
<td>cursus</td>
<td>ante</td>
</tr>
<tr>
<td>1,004</td>
<td>dapibus</td>
<td>diam</td>
<td>Sed</td>
<td>nisi</td>
</tr>
<tr>
<td>1,005</td>
<td>Nulla</td>
<td>quis</td>
<td>sem</td>
<td>at</td>
</tr>
<tr>
<td>1,006</td>
<td>nibh</td>
<td>elementum</td>
<td>imperdiet</td>
<td>Duis</td>
</tr>
<tr>
<td>1,007</td>
<td>sagittis</td>
<td>ipsum</td>
<td>Praesent</td>
<td>mauris</td>
</tr>
<tr>
<td>1,008</td>
<td>Fusce</td>
<td>nec</td>
<td>tellus</td>
<td>sed</td>
</tr>
<tr>
<td>1,009</td>
<td>augue</td>
<td>semper</td>
<td>porta</td>
<td>Mauris</td>
</tr>
<tr>
<td>1,010</td>
<td>massa</td>
<td>Vestibulum</td>
<td>lacinia</td>
<td>arcu</td>
</tr>
<tr>
<td>1,011</td>
<td>eget</td>
<td>nulla</td>
<td>Class</td>
<td>aptent</td>
</tr>
<tr>
<td>1,012</td>
<td>taciti</td>
<td>sociosqu</td>
<td>ad</td>
<td>litora</td>
</tr>
<tr>
<td>1,013</td>
<td>torquent</td>
<td>per</td>
<td>conubia</td>
<td>nostra</td>
</tr>
<tr>
<td>1,014</td>
<td>per</td>
<td>inceptos</td>
<td>himenaeos</td>
<td>Curabitur</td>
</tr>
<tr>
<td>1,015</td>
<td>sodales</td>
<td>ligula</td>
<td>in</td>
<td>libero</td>
</tr>
</tbody>
</table>
</div> {% endblock %}
</div> </div>
</div> </body>
{% endblock %}

index.html

  涉及知识点

  • 模板继承,母版写入block块,在子版里继承的block块定义自己的代码,子模板的头行用extends 加  继承的母版 {% extends "base.html" %}   {% block body %}代码{% endblock %}
  • 静态文件路径配置  STATICFILES_DIRS = (os.path.join(BASE_DIR,‘statics’),)
  • APP路由分发  为更好的管理各个app路径分发情况,更好的做法就每个app都有自己的路径分发器,所以就要使用到django中include路由分发了,把项目下urls.py复制一份到APP下,然后在项目的urls.py下用include引流到APP下,url(r'^crm/', include('app01.urls')),
  • url别名,在路由分发器中,有个name参数是进行别名的,可用于前端调用,如果url地址有变,通过别名照样能访问对应的视图,当然别名对于正则匹配的动态url,需要给视图传参的,就不起作用了,在前端调用别名时,使用{% url 别名 %},这样在渲染的时候,就会自动转化成对应的url
  • 一对一查询,正向查 表.字段名  反向查  表.对表的表名(小写).字段名

bootstrap页面布局的更多相关文章

  1. Bootstrap页面布局3 - BS布局以及流动布局

    1. <h1 class='page-header'>布局<small> 使用bootstrap网格系统布局网页</small></h1> 得到如图所示 ...

  2. Bootstrap页面布局16 - BS导航菜单和其响应式布局以及导航中的下拉菜单

    代码: <div class='container-fluid'> <h2 class='page-header'>导航</h2> <!-- .navrbar ...

  3. Bootstrap页面布局9 - BS列表

    列表: 无序列表(列表中项目内容没有固定的顺序), 有序列表(通常使用在一组有前后顺序的内容上), 描述列表(定义解释一组词汇) 无序列表: <ul> <li>Ueditor编 ...

  4. Bootstrap页面布局5 - 响应式布局(格式)

    旨在优化不同上网设备中页面显示的优化 响应式布局:就是根据浏览窗口的尺寸,改变页面的变化 原理:利用css的media-queries判断浏览窗口的尺寸,在CSS样式表中设置一些规则! 例如: 在&l ...

  5. Bootstrap页面布局2 - 包含BS文件

    如图所示: bootstrap布局基于HTML5,为了使IE8以下也能使用某些HTML5的标签,必须要引入文件:http://html5shiv.googlecode.com/svn/trunk/ht ...

  6. Bootstrap页面布局24 - BS旋转木马功能

    代码: <div class='container-fluid'> <h3 class='page-header'>Bootstrap 旋转木马</h3> < ...

  7. Bootstrap页面布局23 - BS折叠内容

    <div class='container-fluid'> <h3 class='page-header'>Bootstrap 折叠内容</h3> <!--如 ...

  8. Bootstrap页面布局22 - BS工具提示

    当鼠标点击在一个a连接上时,显示提示文字的效果 ----------------  tooltip <div class='container-fluid'> <h3 class=' ...

  9. Bootstrap页面布局20 - BS缩略图

    <div class='container-fluid'> <h2 class='page-header'>Bootstrap 缩略图</h2> <ul cl ...

随机推荐

  1. Oracle学习笔记(5)——查询

    基本查询语句 SELECT [DISTINCT] column_name1,...|* FROM table_name [WHERE conditions] 在SQL*PLUS中设置格式 更改显示字段 ...

  2. Phalcon 訪问控制列表 ACL(Access Control Lists ACL)

    Phalcon在权限方面通过 Phalcon\Acl 提供了一个轻量级的 ACL(訪问控制列表). Access Control Lists (ACL) 同意系统对用户的訪问权限进行控制,比方同意訪问 ...

  3. ActiveMQ介绍和ActiveMQ入门实例

    ActiveMQ百度百科   ActiveMQ入门实例-cnblogs.com      作者用的是5.5的版本,我测试时用的是5.6,按照作者说的整了一下,走得通

  4. 网页中多一些常见效果之伸缩菜单(主要是学习js的书写方法)

    效果如下图: 代码很简单,如下: <!doctype html> <html lang="en"> <head> <meta charse ...

  5. RabbitMQ Performance Testing Tool 性能测试工具

    RabbitMQ Performance Testing Tool 介绍:https://www.rabbitmq.com/java-tools.html RabbitMQ Performance T ...

  6. 使用NPOI读取Excel出错

    使用NPOI读取Excel出错,错误信息:java.io.IOException: Invalid header signature; read 4503608217567241, expected ...

  7. C++设计模式之代理模式

        IPhone 6已经在中国香港开售了,圆了在专卖店等候一个多月苹果粉丝的苹果梦.然而对中国大陆而言.须要到9月17日苹果才在大陆开售.这对中国大陆的粉丝而言,不亚于一种煎熬,因此而滋生一种代购 ...

  8. linux 自启动

    使用chkconfig命令可以查看在不同启动级别下课自动启动的服务(或是程序),命令格式如下:chkconfig --list可能输出如下:openvpn 0:关闭 1:开启 ...... 6:关闭 ...

  9. Echart - 最好最强大效果最丰富的可视化图表插件

    # 官网http://echarts.baidu.com/ # demohttp://echarts.baidu.com/gallery/index.html Echart npm install e ...

  10. 初识Quartz(一)

    首先需要一个任务: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package quartz_proj ...