我的第一个python web开发框架(18)——前台页面与接口整合
Posted AllEmpty
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我的第一个python web开发框架(18)——前台页面与接口整合相关的知识,希望对你有一定的参考价值。
由于我们前后台系统没有分开,所以前台页面调用接口时,可以直接使用后台管理系统已经完成的接口,不过后台管理系统接口的访问加上了登录验证,所以需要将前台要用到的接口进行处理,让它们设置到白名单当中
我们打开main.py文件,在勾子函数中@hook(\'before_request\')中找到下面代码
# 过滤不用做任何操作的路由(即过滤不用进行判断是否登录和记录日志的url) if path_info in [\'/favicon.ico\', \'/\', \'/api/verify/\']: return
这里前面已讲过,是跳过那些需要权限判断和进行日志记录的访问,对于后台上传的图片来说,我们不需要进行日志记录和权限判断,所以在这里添加上日志访问的路由
# 过滤不用做任何操作的路由(即过滤不用进行判断是否登录和记录日志的url) if path_info in [\'/favicon.ico\', \'/\', \'/api/verify/\'] or path_info.find(\'/upload/\') > -1: return
path_info是当前客户端访问的url,通常url是固定的话,我们可以通过in的方式直接进行判断
因为上传的图片统一存放在/upload/这个目录中,而访问图片的路由是/upload/xxxx/xxxxxxxxx.jpg,每张图片访问路径都不一样,新上传的图片就会生成新的链接,url是动态变化的,所以我们使用查找的方式来进行判断当前url是否是图片,如果是的话,则不执行下面的操作。
同样在勾子函数@hook(\'before_request\')中找到下面代码
# 过滤不用进行登录权限判断的路由(登录与退出登录不用检查是否已经登录) url_list = ["/api/login/", "/api/logout/"] if path_info in url_list: pass
为了方便出现问题时及时排查,所以我们会将客户端对接口的访问,以及提交的参数记录到日志中,保存一段时间,所以我们会将一些访问频繁但对分析无关的接口添加到前面过滤处理中。
因为对后台管理系统操作时,我们需要对用户权限进行验证,所以会在勾子中统一进行验证用户是否已经登录成功。但有一些接口我们是不必要进行验证的,比如登录和退出登录接口,如果它们不排除在外的话,那么用户将无法登录,因为每次访问登录接口都会返回你未登录不能访问,这样就会出现死循环,未登录不能访问接口,而不能访问接口则无法进行登录的怪圈当中,所以我们需要对一些无需登录就可以访问的接口进行例外处理。
对于前台获取公司介绍、联系我们、产品分类、产品列表和产品信息的接口,我们可以将它们添加到这里来,进行过滤。
# 过滤不用进行登录权限判断的路由(登录与退出登录不用检查是否已经登录) url_list = ["/api/login/", "/api/logout/", "/api/about/", "/api/contact_us/", "/api/product_class/"] if path_info in url_list or (request.method == \'GET\' and path_info.find(\'/api/product/\') > -1): pass
因为我们使用的是RESTful风格的路由,获取产品信息、修改产品信息和删除产品信息路由url是一样的,只是通过get/put/delete来进行区分,所以我们在处理时,需要获取客户端的提交方式是GET还是PUT或DELETE,然后进行区分处理。
我们知道获取产品信息的接口路由是:@get(\'/api/product/<id:int>/\') ,它会根据产品id的不同而不同,所以我们可以通过request.method == \'GET\' 来判断当前访问提交的是GET方式,而且访问的路径是/api/product/时,我们就不做权限判断处理。
点击main.py运行debug,然后在浏览器上输入:http://127.0.0.1:81/api/about/ 就可以看到已经可以取到数据了
打开index.html页面代码,将公司介绍那部分html代码删掉,替换成下面加上id标签的代码
<img id="about_img" width="600" height="150"> <br><br> <span id="about"></span>
然后我们在底部javascript脚本中添加下面ajax代码,就可以看到展示效果了
//读取服务器记录
$.ajax({
url: "/api/about/",
type: "GET",
dataType: \'json\',
success: function (data) {
$("#about_img").attr(\'src\', data.data.front_cover_img);
$("#about").text(data.data.content);
}
});
产品中心这里需要显示四个产品,所以我们先登录后台管理系统,在产品中心那里可以先录入好产品,如下图
然后打开index.html,找到显示产品的html代码,将它们全部删除,替换成下面内容,用来接收到服务器端记录以后,替换成对应的html
<div class="panel-body" style="height:460px" id="productsDiv"></div>
将代码拉到底部,在javascript中,添加下面代码,它会读取到产品信息以后,对html内容重新进行组合
$.ajax({ url: "/api/product/?rows=4&page=1", type: "GET", dataType: \'json\', success: function (data) { if (data.rows != null && data.rows.length > 0) { for (var i in data.rows) { if (i == 4){ break; } var item = data.rows[i]; var html = \' <div style="float:left; padding-right:6px; padding-bottom:10px"><a href="/product_details.html?id=\' + item.id + \'"><div><img style="width:290px; height:200px" src=\' + item.front_cover_img + \' alt="..." class="thumbnail"></div><div class="text-c" style="padding-top:5px;"><strong>\' + item.name + \'</strong></div></a></div>\' $("#productsDiv").append(html); } } } });
由于前后台合用一个接口,前台接口调用的产口列表是启用状态的,不显示禁用状态的,而后台需要获取所有产品,所以我们要对接口数据处理一下才行,在接口添加一个参数进行判断处理,是否是后台获取数据,前台默认返回启用状态数据
在product.py中找到接口@get(\'/api/product/\'),添加下面处理
# 判断是否是前台提交获取数据 if type != \'backstage\': # 判断是否已经存在查询条件了,是的话在原查询条件后面拼接 if wheres: wheres = wheres + \' and is_enable=1\' else: wheres = \'where is_enable=1\'
在后台产品中心页面的html中,访问/api/product/接口时,也添加上这个参数,大家在products_list.html页面中查找/api/product/,将它改为:/api/product/?type=backstage 或 /api/product/?type=backstage&product_class_id=
这样再刷新首页,就会出现下面效果了:
关于我们页面和联系我们页面比较简单,只需要将页面中间显示的内容删除,替换成<span id="content"></span>
在页面底部的javascript中添加下面代码,效果就可以直接看到了。注:联系我们页面只需要将/api/about/替换成/api/contact_us/就可以了
$.ajax({ url: "/api/about/", type: "GET", dataType: \'json\', success: function (data) { $("#content").html(data.data.content); } });
效果图:
打开产品中心products.html页面,这个页面有两个位置需要从服务器端读取数据的,一是分类列表,一是产品列表,需要写两个ajax。另外,用户从菜单栏或首页进来时,有可能没有带分类id,所以在写js时,需要进行专门的处理,没有id的,需要从分类列表的ajax中获取一个id,用作产品列表查询,具体大家直接看javascript代码就知道了
首先将分类列表项删除,替换成<ol class="linenums" id="product_class"></ol>,将产品列表全部html代码删除,替换成<div class="panel-body" id="products"></div>
在页面底部的javascript中添加下面代码,效果就可以直接看到了。
由于前后台合用一个接口,需要和产品列表接口做样的处理,区分前后台获取数据
var id = getQueryString(\'id\'); if (id != \'\'){ get_product_list(id); } $.ajax({ url: "/api/product_class/", type: "GET", dataType: \'json\', success: function (data) { if (data.rows != null && data.rows.length > 0) { for (var i in data.rows) { var item = data.rows[i]; if (id == \'\') { id = item.id; get_product_list(id); } var html = \' <li><a href="/products.html?id=\' + item.id + \'">\' + item.name + \'</a></li>\'; $("#product_class").append(html); } } } }); function get_product_list(id) { $.ajax({ url: "/api/product/?product_class_id=" + id, type: "GET", dataType: \'json\', success: function (data) { if (data.rows != null && data.rows.length > 0) { for (var i in data.rows) { var item = data.rows[i]; var html = \'<div style="float:left; padding-right:20px; padding-bottom:20px"><a href="/product_details.html?id=\' + item.id + \'"><div><img style="width:290px; height:200px" src="\' + item.front_cover_img + \'" alt="\' + item.name + \'" class="thumbnail"></div><div class="text-c" style="padding-top:5px;"><strong>\' + item.name + \'</strong></div></a></div>\' $("#products").append(html); } } } }); } /*获取url中的参数*/ function getQueryString(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); var r = window.location.search.substr(1).match(reg); if (r != null) return r[2]; return \'\'; }
我们打开产品详情页面product_details.html,从这个页面的原型就可以看到,它也有两个地方需要与服务器接口交互,一个是产品分类列表,这个同产品中心的代码一样,复制过来就可以了。另一个是产品信息的展示,需要通过ajax从服务器端获取指定的产品信息,然后再写入到页面中。
我们可以先在后台编辑好一个产品内容,如下图
将分类列表项删除,替换成<ol class="linenums" id="product_class"></ol>,为产品图片加上id:<img style="width:400px; height:300px" src="" alt="..." class="thumbnail" id="front_cover_img">
删除产品信息展示内容,替换成:<div style="float:left; font-size: 16px" id="product_info"></div>
删除产品描述替换成:<div class="panel-body" id="content"></div>
在页面底部的javascript中添加下面代码,效果就可以直接看到了。
$.ajax({ url: "/api/product_class/", type: "GET", dataType: \'json\', success: function (data) { if (data.rows != null && data.rows.length > 0) { for (var i in data.rows) { var item = data.rows[i]; var html = \' <li><a href="/products.html?id=\' + item.id + \'">\' + item.name + \'</a></li>\'; $("#product_class").append(html); } } } }); var id = getQueryString(\'id\'); if (id != \'\') { $.ajax({ url: "/api/product/" + id + "/", type: "GET", dataType: \'json\', success: function (data) { if (data.state == 0) { $("#front_cover_img").attr(\'src\', data.data.front_cover_img); var html = \'产品名称:\' + data.data.name + \'<br><br>产品编号:\' + data.data.code + \'<br><br>产品规格:\' + data.data.standard + \'<br><br>保 质 期:\' + data.data.quality_guarantee_period + \'<br><br>产 地:\' + data.data.place_of_origin + \'<br><br>\'; $("#product_info").append(html); $("#content").append(data.data.content); } } }); } /*获取url中的参数*/ function getQueryString(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); var r = window.location.search.substr(1).match(reg); if (r != null) return r[2]; return \'\'; } </script>
到此,我们整个代码部分就全部完成了,接下来要做的就是服务器的部署工作了
本文对应的源码下载(完整代码)
版权声明:本文原创发表于 博客园,作者为 AllEmpty 本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
python开发QQ群:669058475(本群已满)、733466321(可以加2群) 作者博客:http://www.cnblogs.com/EmptyFS/
以上是关于我的第一个python web开发框架(18)——前台页面与接口整合的主要内容,如果未能解决你的问题,请参考以下文章
我的第一个python web开发框架(16)——产品分类管理
我的第一个python web开发框架(11)——工具函数包说明