Falsk框架优势:
1.轻巧
2.简洁
3.扩展性强(个人认为最重要的特点)
4.核心(werkzeug和jinja2)jinja2就是指模板引擎。
非常适用于小型网站
非常适用于开发web服务的API
开发大型网站无压力,但代码架构需要自己设计,开发成本取决于开发者的能力和经验
各方面性能均等于或优于Django
Django自带的或第三方的好评如潮的功能,Flask上总会找到与之类似第三方库
Flask灵活开发,Python高手基本都会喜欢Flask,但对Django却可能褒贬不一
Flask与关系型数据库的配合使用不弱于Django,而其与NoSQL数据库的配合远远优于Django
Flask比Django更加Pythonic,与Python的philosophy更加吻合
如下是对单表增删改查的具体实例
注:本篇文章是在上篇文章的基础上进行的更改,因为在已有的后台处理上,对不同的数据表的数据处理其实就是sql语句的不同以及封装数据还有前台js中的ajax略有差异,方法名称没有太大改变,但是本篇文章在原来的基础上又在后面新增加了一个bootstrap的模态框用于实现增加数据的操作;具体代码实现如下(文件目录结构与上片大体一致):
shopcontroller.py文件:
from flask import render_template, Blueprint, request
from service.shopservice import ShopService
from entity.shop import Shop
import json
shopcontroller = Blueprint('shopcontroller',__name__)
shopService=ShopService()
#删除功能
@shopcontroller.route('/removeshop.do',methods = ['POST','GET'])
def goRemoveShop():
shopId = request.args.get('shopId')
job_city = request.form.get('job_city')
shop = Shop()
shop.job_position = job_city
result = shopService.removeShop(shopId)
shopList = shopService.findPageShopList(shop,16,1)
return render_template('systeminfo/messageinfo.html',shopList = shopList,message="删除成功" if result>0 else "删除失败") #前端用的key
#确认修改
@shopcontroller.route('/checkshopname.do',methods = ['POST','GET'])
def checkShopName():
shopdata = request.get_data()
shopDict = json.loads(shopdata)
shop = Shop()
shop.job_id = shopDict.get('shopId') #将数据赋给user实体的属性
shop.job_position=shopDict.get('shopName')
shop.job_MMoney = shopDict.get('shopPrice')
shop.job_city = shopDict.get('shopNum')
result =shopService.updateShop(shop)
dicts={}
if result:
dicts = {'code':1}
else:
dicts = {'code':0}
return json.dumps(dicts)
pass
#查询以及分页
@shopcontroller.route('/ajaxshopinfo.do', methods=['POST', 'GET'])
def getShopInfo():
shopData = request.get_data()
shopDict = json.loads(shopData)
tData = {}
shop = Shop()
shop.job_city = shopDict.get('shopName')
currentPage = int(shopDict.get('currentPage'))
pageSize = int(shopDict.get('pageSize'))
opr = shopDict.get('opr')
shopId = shopDict.get('shopId')
shop.job_id = shopId
result = shopService.findPageShopList(shop, pageSize, currentPage)
counts = shopService.countShops(shop)
totalPage = 0
if(counts%pageSize == 0):
totalPage = counts//pageSize
else:
totalPage = counts // pageSize + 1
pass
returnData = {'code':1, 'shopData':result, 'pageSize':pageSize, 'currentPage':currentPage, 'totalPage':totalPage, 'opr':'search'}
return json.dumps(returnData)
pass
#确认添加
@shopcontroller.route('/submits.do', methods=['POST', 'GET'])
def submits():
Text = request.get_data()
TextDict = json.loads(Text)
shop = Shop()
shop.job_position = TextDict.get('jobposition')
shop.job_MMoney = TextDict.get('jobmoney')
shop.job_city= TextDict.get('jobcity')
result = shopService.submits(shop)
print(result)
dicts = {}
if result:
dicts = {'code': 1}
else:
dicts = {'code': 0}
return json.dumps(dicts)
pass
basedao.py(连接数据库以及提供通用的数据库接口文件)
import pymysql
import json
import os
#DBUtils.py
class BaseDao():
def __init__(self,configPath = 'pymysql.json'):
self.__connection =None
self.__cursor = None
self.__config = json.load(open(os.path.dirname(__file__) + os.sep + configPath,'r')) #通过json配置获得数据的连接配置信息
print(self.__config)
pass
def getConnection(self):
#当有连接对象时,直接返回连接对象
if self.__connection:
return self.__connection
#否则通过建立新的连接对象
try:
self.__connection = pymysql.connect(**self.__config)
return self.__connection
except pymysql.MySQLError as e:
print("Exception"+str(e))
pass
pass
#用于执行Sql语句的通用方法
def execute(self,sql,params=None):
try:
self.__cursor = self.getConnection().cursor()
#execute:返回的是修改数据的条数
if params:
result = self.__cursor.execute(sql,params)
else:
result = self.__cursor.execute(sql)
return result
except (pymysql.MySQLError,pymysql.DatabaseError,Exception) as e:#捕获多个异常
print("出现数据库访问异常:"+str(e))
self.rollback()
pass
pass
pass
def fetch(self):
if self.__cursor: #提高代码健壮性
return self.__cursor.fetchall()
pass
def fetchOne(self):
if self.__cursor: #提高代码健壮性
return self.__cursor.fetchone()
pass
def commit(self):
if self.__connection:
self.__connection.commit() #回滚问题
pass
def rollback(self):
if self.__connection:
self.__connection.rollback()
pass
def getLastRowId(self):
if self.__cursor:
return self.__cursor.lastrowid
def close(self):
if self.__cursor:
self.__cursor.close()
if self.__connection:
self.__connection.close()
pass
if __name__=="__main__":
ms = BaseDao()
pymysql.json(数据库信息配置文件)
{"host":"127.0.0.1","user":"root","password":"root", "database" :"你的数据库","port":你的数据库密码}
shopdao.py文件
from .basedao import BaseDao
class ShopDao(BaseDao):
#删除功能的函数
def removeShop(self,shopId):
try:
sql = "delete from job_position where job_id=%s"
self.getConnection()
result = self.execute(sql, (shopId,))
self.commit() # 执行语句后要提交
finally:
self.close()
return result
pass
#修改数据库数据
def updateShop(self,shop):
try:
sql = "update job_position set job_city=%s,job_MMoney=%s,jobposition=%s where job_id=%s"
self.getConnection()
result = self.execute(sql,(shop.job_city,shop.job_MMoney,shop.job_position,shop.job_id))
self.commit() # 执行语句后要提交
finally:
self.close()
return result
pass
#支持查询分页
def findPageShopList(self, shop, pageSize, currentPage):
try:
params = []
# sql语句和param就需要是动态
sql = "select * from job_position where 1=1 " # where 1=1 便于增加and
if shop.job_city:
sql += " and job_city like %s "
params.append('%' + shop.job_city + '%') # 支持模糊查询
pass
startRow = (currentPage - 1) * pageSize
sql += "limit %s, %s"
params.append(startRow)
params.append(pageSize)
self.getConnection()
self.execute(sql, params)
result = self.fetch()
finally:
self.close()
return result
pass
def countShops(self, shop):
params = []
# sql语句和params就需要是动态
sql = "select count(*) from job_position where 1=1 " # where 1=1是为了便于增加and
if shop.job_city:
sql += " and job_city like %s " # 模糊查询
params.append('%' + shop.job_city + '%')
pass
self.getConnection()
self.execute(sql, params)
result = self.fetchOne()
return result
pass
pass
def submits(self,shop):
try:
sql = "insert into job_position(job_city,job_MMoney,jobposition) values(%s,%s,%s)"
self.getConnection()
result = self.execute(sql,(shop.job_city,shop.job_MMoney,shop.job_position))
self.commit() #执行语句后要提交
finally:
self.close()
return result
pass
shop.py文件(初始化职位实体属性文件)
class Shop():
def __init__(self):
self.__job_id = None
self.__job_position = None
self.__job_MMoney = None
self.__job_city = None
@property
def job_id(self):
return self.__job_id
@job_id.setter
def job_id(self, job_id):
self.__job_id = job_id
@property
def job_position(self):
return self.__job_position
@job_position.setter
def job_position(self, job_position):
self.__job_position = job_position
@property
def job_MMoney(self):
return self.__job_MMoney
@job_MMoney.setter
def job_MMoney(self, job_MMoney):
self.__job_MMoney = job_MMoney
@property
def job_city(self):
return self.__job_city
@job_city.setter
def job_city(self, job_city):
self.__job_city = job_city
shopservice.py文件
from dao.shopdao import ShopDao
from entity.shop import Shop
class ShopService():
#删除 id
def removeShop(self,shopId):
shopDao = ShopDao()
return shopDao.removeShop(shopId)
pass
#修改
def updateShop(self,shop):
shopDao = ShopDao()
return shopDao.updateShop(shop) #对数据库进行更新操作
#分页以及查询
def findPageShopList(self, shop, pageSize, currentPage):
shopDao = ShopDao()
return shopDao.findPageShopList(shop,pageSize,currentPage)
pass
#计算用户个数
def countShops(self, shop):
shopDao = ShopDao()
return shopDao.countShops(shop)[0]
pass
#确认添加
def submits(self,shop):
shopDao = ShopDao()
return shopDao.submits(shop)
pass
shop.js文件
//删除
function submitRemoveShop(shopId) {
if(confirm("确定要删除吗?")){
window.location.href="/removeshop.do?shopId="+shopId
}
}
//修改
function submitModifyShop(id) {
//console.log('#list-line' + id +" td")
$('#list-lines' + id +" td").attr('contentEditable',true);
// $('#id').attr("readonly","readonly");
}
//点击修改完成按钮的功能,动态将修改的数据控制层(usercontroller.py文件)
function submitModifyShops(id){
$.ajax({
type: 'post', // 传数据的方式
url: '/checkshopname.do',
dataType: 'json', // xml、json、script、html
data:JSON.stringify({
'shopId': $("td[name='shopId"+id+"']").html(), // $('#userName') == document.getElementById('userName')
'shopName': $("td[name='shopName"+id+"']").html(),
'shopPrice': $("td[name='shopPrice"+id+"']").html(),
'shopNum': $("td[name='shopNum"+id+"']").html(),
}),
error: function(xhr, err){
alert('请求失败,请检查,' + err + '!')
},
success: function(data, textStatus){ // success对应的回调函数的第一个参数,是服务器返回的数据
if(data.code==1){
alert("修改完成!")
//console.log("成功")
$('#list-lines' + id +" td").attr('contentEditable',false)
}
}
});
}
function getShopData(currentPage, pageSize, opr, shopId) {
shopName = document.searchForms.shopName.value
if(opr == 'del'){
if(!confirm('确定要删除吗?')){
return false
}
}
$.ajax({
type: 'post', // 传数据的方式
url: '/ajaxshopinfo.do',
dataType: 'json', // xml、json、script、html
data:JSON.stringify({
'shopId':shopId,
'shopName':shopName,
'pageSize': pageSize,
'currentPage': currentPage,
'opr': opr
}),
error: function(xhr, err){
alert('请求失败,请检查,' + err + '!')
},
success: function(data, textStatus){ // success对应的回调函数的第一个参数,是服务器返回的数据
if(data.code == 1 && opr != 'update'){
var htmlTexts = ""
for(var i =0;i <data.shopData.length;i++){
htmlTexts +=' <tr id="list-lines'+data.shopData[i][0]+'" >\n' +
' <td><input type="checkbox" name="shopId" value='+ data.shopData[i][0] +'/></td>\n' +
' <td name="shopId'+ data.shopData[i][0] +'">'+ data.shopData[i][0] +'</td>\n' +
' <td name="shopName'+ data.shopData[i][0] +'">'+ data.shopData[i][1] +'</td>\n' +
' <td name="shopPrice'+ data.shopData[i][0] +'">'+ data.shopData[i][4] +'</td>\n' +
' <td name="shopNum'+ data.shopData[i][0] +'">'+ data.shopData[i][12] +'</td>\n' +
' <td>\n' +
' <a onclick=submitRemoveShop('+ data.shopData[i][0] +')>删除</a> \n' +
' <a onclick=submitModifyShop('+ data.shopData[i][0] +')>修改</a> \n' +
' <a onclick=submitModifyShops('+ data.shopData[i][0] +')>完成</a>\n' +
' </td>\n' +
' \n' +
' </tr>'
}
pageTexts = '<tr><td colspan="8" align="center">---------------------------------------------------------------------------------------------------</td></tr>' +
'<tr><td colspan="8" align="center">'+ '当前第' + data.currentPage + '页 总共有' + data.totalPage + '页 ';
if(data.currentPage <= 1) {
pageTexts += '首页 上一页 ';
}else{
pageTexts += '<a href="javascript:getShopData(1,16,\'search\', 0);">首页</a> ' +
'<a href="javascript:getShopData(' + (data.currentPage - 1) + ', 16, \'search\', 0);">上一页</a> ';
}
if(data.currentPage >= data.totalPage){
pageTexts += '下一页 尾页 ';
}else {
pageTexts += '<a href="javascript:getShopData(' + (data.currentPage + 1) + ', 16, \'search\', 0);">下一页</a> ' +
'<a href="javascript:getShopData(' + data.totalPage + ', 16, \'search\', 0);">尾页</a> ';
}
pageTexts +='</td></tr>'
$('#shopDataBody').empty()
$('#shopDataBody').append(htmlTexts)
$('#shopDataBody').append(pageTexts)
document.searchForm.currentPage.value = data.currentPage
document.searchForm.pageSize.value=data.pageSize
}
}
});
}
$(document).ready(
function(){
getShopData(1, 16, 'search', 0)
}
)
function insert() {
template = document.getElementById("theTemplate").innerHTML ;
// console.log(template)//获取index.html界面模态框代码
$('#model').append(template);
}
function submits(){
jobposition = $("input[name='jobposition']:first").val()
jobmoney = $("input[name='jobmoney']:first").val()
jobcity = $("input[name='jobcity']:first").val()
$.ajax({
type: 'post', // 传数据的方式
url: '/submits.do',
dataType: 'json', // xml、json、script、html
data: JSON.stringify({
'jobposition':jobposition,
'jobmoney':jobmoney,
'jobcity':jobcity,
}),
error: function (xhr, err) {
alert('请求失败,请检查,' + err + '!')
},
success: function (data, textStatus) {
if(data.code==1){
alert("数据写入成功")
}
}
})
}
messageinfo.html文件(管理员界面)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>后台管理界面</title>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script type="text/javascript" src="{{ url_for('static',filename="js/formvalidator.js") }}"></script>
<script type="text/javascript" src="{{ url_for('static',filename="js/shop.js") }}"></script>
</head>
<body>
<div class="container">
<h2>管理员界面</h2>
<br/>
<div class="row clearfix">
<div class="col-md-12 column">
<div class="tabbable" id="tabs-200351">
<ul class="nav nav-tabs">
<li>
<a href="#panel-200936" data-toggle="tab">数据管理</a>
</li>
<li>
<a href="#panel-200937" data-toggle="tab">订单管理</a>
</li>
<li>
<a href="#panel-200938" data-toggle="tab">销量可视化</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="panel-200936">
<br/>
<!--查询-->
<div id="searchBoxs"> <!-- action="/gouserinfo.do" -->
<form method="post" name="searchForms">
<br/>
城市名:<input type="text" name="shopName">
<input type="hidden" name="currentPage" value="1"/> <!--hidden为不可见-->
<input type="hidden" name="pageSize" value="16"/>
<input type="button" value="查询" onclick="getShopData(1, 16, 'search', 0)">
<input type="button" value="添加" onclick="insert()" data-toggle="modal" data-target="#myModal">
</form>
</div>
<script type="text/html" id="theTemplate">
{# <!-- 按钮触发模态框 -->#}
{# <button class="btn btn-primary" data-toggle="modal" data-target="#myModal">#}
{# 开始演示模态框#}
{#{ </button>#}
{# <!-- 模态框(Modal)-->#}
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="display: none;">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-hidden="true">
</button>
<h2 class="modal-title" id="myModalLabel">
请插入职位信息
</h2>
</div>
<div class="modal-body">
<div id="orderCon" style="text-align:center">
职位名: <input type="text" name="jobposition" value="" /><br/><br/>
月薪: <input type="text" name="jobmoney" value="" /><br/><br/>
城市: <input type="text" name="jobcity" value="" /><br/><br/>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default"
data-dismiss="modal">关闭
</button>
<button type="button" class="btn btn-primary" id="orderSubmit" onclick="submits()" data-dismiss="modal">
添加
</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</script>
<div id="model">
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="display: none;">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-hidden="true">
</button>
<h2 class="modal-title" id="myModalLabel">
请插入职位信息
</h2>
</div>
<div class="modal-body">
<div id="orderCon" style="text-align:center">
职位名: <input type="text" name="jobposition" value="" /><br/><br/>
月薪: <input type="text" name="jobmoney" value="" /><br/><br/>
城市: <input type="text" name="jobcity" value="" /><br/><br/>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default"
data-dismiss="modal">关闭
</button>
<button type="button" class="btn btn-primary" id="orderSubmit" onclick="submits()" data-dismiss="modal">
添加
</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>
<!--动态生成数据库中商品信息的表格-->
<table class="dataTables" align="center" style="width: 100%">
<thead>
<tr>
<th align="center">
<input type="button" value="全选"/>
<input type="button" value="反选"/>
</th>
<th>职位编号</th>
<th>职位名</th>
<th>月薪</th>
<th>城市</th>
</tr>
</thead>
<tbody id="shopDataBody">
{# {% for shop in shopList %}#}
{# <tr id="list-lines{{ shop.shopId }}" >#}
{# <td><input type="checkboxs" name="shopId" value="{{ shop.shopId }}"/></td>#}
{# <td name="shopId{{ shop.shopId }}">{{ shop.shopId }}</td>#}
{# <td name="shopName{{ shop.shopId }}">{{ shop.shopName }}</td>#}
{# <td name="shopPrice{{ shop.shopId }}">{{ shop.shopPrice }}</td>#}
{# <td name="shopNum{{ shop.shopId }}">{{ shop.shopNum }}</td>#}
{# <td name="shopClassfiy{{ shop.shopId }}">{{ shop.shopClassfiy }}</td>#}
{# <td name="shopImgUrl{{ shop.shopId }}">{{ shop.shopImgUrl }}</td>#}
{# <td>#}
{# <a onclick="getShopData(1, 16, 'del', 0)">删除</a> #}
{# <a id="xg" onclick="submitModifyShop({{ shop.shopId }})">修改</a> #}
{# <a id="wc" onclick="submitModifyShops({{ shop.shopId }})">完成</a>#}
{# </td>#}
{# </tr>#}
{# {% endfor %}#}
</tbody>
</table>
{# 第二块结尾 #}
</div>
<div class="tab-pane" id="panel-200937">
<br/>
<!--查询-->
<div id="searchBoxss"> <!-- action="/gouserinfo.do" -->
<form method="post" name="searchFormss">
<br/>
用户名:<input type="text" name="orderName">
<input type="hidden" name="currentPage" value="1"/> <!--hidden为不可见-->
<input type="hidden" name="pageSize" value="16"/>
<input type="button" value="查询" onclick="getShopData(1, 16, 'search', 0)">
</form>
</div>
<!--动态生成数据库中订单信息的表格-->
<table class="dataTables" align="center" style="width: 100%">
<thead>
<tr>
<th>订单编号</th>
<th>用户编号</th>
<th>商品名</th>
<th>购买数量</th>
<th>金额</th>
<th>发件人地址</th>
<th>收件人姓名</th>
<th>收件人电话</th>
<th>收件人地址</th>
<th>操作</th>
</tr>
</thead>
<tbody id="orderDataBody">
</tbody>
</table>
{# 第三块结尾#}
</div>
<div class="tab-pane" id="panel-200938">
<p>
销量界面暂未开发
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
app.py文件(启动程序)
from flask import Flask,render_template,request,session,Response
from controller.shopcontroller import shopcontroller
from datetime import timedelta
app = Flask(__name__)
app.config['DEBUG']=True
app.config['SECRET_KEY'] ="fggggjjjhgggg"
app.config['PERMANENT_SESSION_LIFETIME']=timedelta(minutes=30)
app.register_blueprint(shopcontroller) #数据层
@app.route('/',methods =['POST','GET'])
def index():
return render_template('systeminfo/messageinfo.html')
if __name__ == '__main__':
app.run(host="10.0.14.107",port=8080)
至此,是本文章的全部代码内容,如下图是增加功能的模态框界面效果:
下篇文章见!!!