一:背景
面包屑导航(BreadcrumbNavigation)这个概念来自童话故事"汉赛尔和格莱特",当汉赛尔和格莱特穿过森林时,不小心迷路了,但是他们发现在沿途走过的地方都撒下了面包屑,让这些面包屑来帮助他们找到回家的路。所以,面包屑导航的作用是告诉访问者他们目前在网站中的位置以及如何返回。
二:作用
1、让用户了解当前所处位置,以及当前页面在整个网站中的位置。
2、体现了网站的架构层级,能够帮助用户快速学习和了解网站内容和组织方式,从而形成很好的位置感。
3、提供返回各个层级的快速入口,方便用户操作。
4、Google已经将面包屑导航整合到搜索结果里面,因此优化面包屑导航每个层级的名称,多使用关键字,都可以实现SEO优化。面包屑路径,对于提高用户体验来说,是很有帮助的。
5、方便用户,面包屑主要用于为用户提供导航一个网站的次要方法,通过为一个大型多级网站的所有页面提供面包屑路径,用户可以更容易的定位到上一次目录,引导用户通行;
6、减少返回到上一级页面的点击或操作,不用使用浏览器的“返回”按钮或网站的主要导航来返回到上一级页面;
7、不用常常占用屏幕空间,因为它们通常是水平排列以及简单的样式,面包屑路径不会占用页面太多的空间。这样的好处是,从内容过载方面来说,他们几乎没有任何负面影响;
8、降低跳出率,面包屑路径会是一个诱惑首次访问者在进入一个页面后去浏览这个网站的非常好的方法。比如说,一个用户通过谷歌搜索到一个页面,然后看到一个面包屑路径,这将会诱使用户点击上一级页面去浏览感兴趣的相关主题。这样,从而,可以降低网站的总体跳出率。
9、有利于百度蜘蛛对网站的抓取,蜘蛛直接沿着那个链走就可以了,很方便。
10、面包屑有利于网站内链的建设,用面包屑大大增加了网站的内部连接,提高用户体验。
##三:分类 ``` 一、基于位置的面包屑导航 这种类型是最常见的。这种类型的面包屑导航可以很好的指出当前页面与整个站点的层次结构。这种面包屑导航可以显示当前页面的前一个页面或者目录的链接。可以使访客了解自己的位置,以及可以更快的找到自己想要到达的页面。可以很好的提高用户的友好体验。 二、基于属性的面包屑导航 这种面包屑导航最常出现在电子商务站点。这种面包屑导航可以很好的指出当前页面内产品的其他属性或者类别。对于一个产品来说,所具有的属性往往不只有一种,而通过这种面包屑导航可以给消费者一个更加直观的了解。 三、基于路径的面包屑导航 这种面包屑导航是最不常见到的。这种面包屑导航和上文所说的童话故事类型很像。他们可以显示访客在到达页面前所访问过的网页的链接。这种面包屑导航不是很受欢迎,因为他们的功能基本上是和前进和后退的按钮是一样的。 ```
##四:示例 ``` 网站导航 基于位置(Location-based)的面包屑向用户显示他们在网站的哪一个级别页面 。它们一般典型的用于有多个级别(一般是多于两级)的导航方案。在下面的例子中(来自于SitePoint),每一个页面的文本链接表示它比它右边的文本链接高一级。 A 表明当前在网站内的位置。 B 提供指向先前访问过的页面(或网站)和其他区域的捷径。 本质上,它是网站结构的线性表示。Web上的定位面包屑路径所展示的不是导航的历史,而是在整个网站中某个固定的位置。就是说,不管用户是如何到达location 页面,面包屑路径都是一样的。 ```
## 五:代码 ## 5:.1:middlewares.py
import re
from django.shortcuts import HttpResponse, render, redirect
from django.utils.deprecation import MiddlewareMixin
from rbac import models
class PermissonMiddleWare(MiddlewareMixin):
def process_request(self, request):
# 白名单放行
# if request.path in ['/login/','/admin/*']: #你会发现admin都看不了了,admin里面所有的url都不能访问了,所以我们应该让admin开头的url都放行
for i in ['/login/', '/admin/.*']:
ret = re.search(i, request.path)
if ret:
return None
# 登录认证 校验是否登陆
user = request.session.get('user')
if not user:
return redirect('login')
# 面包屑 1
# layout是 所有的请求走完以后,走到url,走到视图函数,视图函数返回页面 加载的
# 走完以后有个request对象,把这个menu_breadcrumb 放到request对象里
# 请求走完以后 request 里有 menu_breadcrumb
request.menu_breadcrumb = [
{'title': '首页', 'url': 'javascript:void(0);'},
# {'title':'客户列表','url':'/customer/list/;'},
]
# 生成菜单之前需要权限认证
# 权限认证
for item in request.session['permisson_list']:
# permisson_list是列表套字典
# 在session注入了 pid 和 pk ,不是单独的url了
# [
# {'url':'/customer/add/','pid':'1','pk':1}
#
# ]
reg = '^%s$' % item['url']
ret = re.search(reg, request.path)
if ret:
request.show_id = item['pid']
# 直接给request这个对象添加一个属性
# 中间件访问以后 request多了一个show_id,就是访问的url里面自己的pid
#
# 把pid 给 show_id
# request.show_id = item['pk']
# 面包屑 2
if item['pid'] == item['pk']:
# Item就是匹配的url的那套数据
# 如果 pid==pk 就是 当前请求的是 菜单的url 是一级的面包屑,直接添加到里面
request.menu_breadcrumb.append({'title': item['title'], 'url': request.path})
# 不相等的需要添加两个
else:
obj = models.Permission.objects.filter(pk=item['pid']).first()
l1 = [
{'title': obj.title, 'url': obj.url}, # 父级菜单 父权限
{'title': item['title'], 'url': request.path}
# 子菜单 子权限就是当前访问的url
]
request.menu_breadcrumb.extend(l1) # 用extend 添加进去
return None
else:
return HttpResponse('不好意思,权限不够!!无权访问!')
# 注意如果url为/customers/edit/1/,但是我们权限里面存的是/customers/edit/(d+)/,
# 这两个字符串能够匹配上吗?不能,但是应不应该放行,应该,所以需要正则搞定!自己去搞定吧!
# 直接按照这种方式写肯定是不行的
# if not current_path in request.session['permisson_list']:
# return HttpResponse('无权访问!')
5.2:layout.py
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>面包屑</title>
<link rel="shortcut icon" href="{% static 'imgs/luffy-study-logo.png' %} ">
<link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.css' %} "/>
<link rel="stylesheet" href="{% static 'plugins/font-awesome/css/font-awesome.css' %} "/>
<link rel="stylesheet" href="{% static 'css/commons.css' %} "/>
<link rel="stylesheet" href="{% static 'css/nav.css' %} "/>
<link rel="stylesheet" href="{% static 'css/menu.css' %}">
<style>
body {
margin: 0;
}
.no-radius {
border-radius: 0;
}
.no-margin {
margin: 0;
}
.pg-body > .left-menu {
background-color: #EAEDF1;
position: absolute;
left: 1px;
top: 48px;
bottom: 0;
220px;
border: 1px solid #EAEDF1;
overflow: auto;
}
.pg-body > .right-body {
position: absolute;
left: 225px;
right: 0;
top: 48px;
bottom: 0;
overflow: scroll;
border: 1px solid #ddd;
border-top: 0;
font-size: 13px;
min- 755px;
}
.navbar-right {
float: right !important;
margin-right: -15px;
}
.luffy-container {
padding: 15px;
}
.left-menu .menu-body .static-menu {
}
</style>
</head>
<body>
<div class="pg-header">
<div class="nav">
<div class="logo-area left">
<a href="#">
<img class="logo" src="{% static 'imgs/logo.svg' %}">
<span style="font-size: 18px;">面包屑 </span>
</a>
</div>
<div class="left-menu left">
<a class="menu-item">资产管理</a>
<a class="menu-item">用户信息</a>
<a class="menu-item">信息管理</a>
<div class="menu-item">
<span>使用说明</span>
<i class="fa fa-caret-down" aria-hidden="true"></i>
<div class="more-info">
<a href="#" class="more-item">管他什么菜单</a>
<a href="#" class="more-item">实在是编不了</a>
</div>
</div>
</div>
<div class="right-menu right clearfix">
<div class="user-info right">
<a href="#" class="avatar">
<img class="img-circle" src="{% static 'imgs/default.png' %}">
</a>
<div class="more-info">
<a href="#" class="more-item">个人信息</a>
<a href="#" class="more-item">注销</a>
</div>
</div>
<a class="user-menu right">
消息
<i class="fa fa-commenting-o" aria-hidden="true"></i>
<span class="badge bg-success">2</span>
</a>
<a class="user-menu right">
通知
<i class="fa fa-envelope-o" aria-hidden="true"></i>
<span class="badge bg-success">2</span>
</a>
<a class="user-menu right">
任务
<i class="fa fa-bell-o" aria-hidden="true"></i>
<span class="badge bg-danger">4</span>
</a>
</div>
</div>
</div>
<div class="pg-body">
<div class="left-menu">
<div class="menu-body">
{% load rbac %}
{% menu request %}
{# 自定义标签增加了代码的复用性 #}
{# {% for foo in request.session.permisson_menu_list %}#}
{##}
{# <div>#}
{# <i class="fa {{ foo.icon }}"></i>#}
{# <a href="{{ foo.url }}">{{ foo.title }}</a>#}
{# </div>#}
{##}
{##}
{# {% endfor %}#}
</div>
</div>
<div class="right-body">
<div>
<ol class="breadcrumb no-radius no-margin" style="border-bottom: 1px solid #ddd;">
{# <li><a href="javascript:viod(0)">首页</a></li>#}
{# <li class="active">客户管理</li>#}
{% for bread in request.menu_breadcrumb %}
{% if forloop.last %}
<li><span>{{ bread.title }}</span></li>
{% else %}
<li><a href="{{ bread.url }}">{{ bread.title }}</a></li>
{% endif %}
{% endfor %}
</ol>
</div>
{% block content %} {% endblock %}
</div>
</div>
<script src="{% static 'js/jquery-3.3.1.min.js' %} "></script>
<script src="{% static 'plugins/bootstrap/js/bootstrap.js' %} "></script>
<script src="{% static 'js/menu.js' %} "></script>
{% block js %} {% endblock %}
</body>
</html>