app.py ---->jox_restful/xxx.py ----> jox_api/xxx.py ----> jox_api/Mysql.py or jox_api/Redis.py
app = Flask(__name__)
CORS(app, supports_credentials=True)
api = Api(app)
# 设置路由
api.add_resource(Upload.UploadRoute, '/api/upload')
api.add_resource(Shop.GetShopRoute, '/api/shop_list')
api.add_resource(Shop.GetShopInfoRoute, '/api/shop_inf')
api.add_resource(Shop.GetCommentRoute, '/api/comment_list')
api.add_resource(Shop.AddCommentRoute, '/api/add_comment')
api.add_resource(Shop.GetFoodRoute, '/api/food_list')
api.add_resource(User.LoginRoute, '/api/login')
api.add_resource(User.AddUserRoute, '/api/add_user')
api.add_resource(User.GetCodeRoute, '/api/code')
api.add_resource(User.GetUserRoute, '/api/user_inf')
if __name__ == '__main__':
app.run(host='127.0.0.1',port=8081)
Shop.py:店铺相关
//获取店铺,根据keyword搜索
class GetShopRoute(Resource):
@Auth.permission(identifier="any")
def post(self):
try:
self.parser = reqparse.RequestParser()
self.shopClass = Shop.Shop()
self.parser.add_argument('keyword', type=str, help='keyword: type is str')
self.args = self.parser.parse_args()
self.keyword = self.args['keyword']
self.restatus = self.shopClass.get_shop(self.keyword)
return self.restatus, 200
except Exception as e:
print(e)
return {"code":-1,"msg":str(e)},200
Shop.py:店铺相关
//获取店铺,根据keyword搜索
class Shop():
def __init__(self):
self.mysqlClass = Mysql.MySQL()
def get_shop(self,keyword):
try:
self.sql = "select * from shop where CONCAT(name,module,scene,type,address) like \'%%%s%%\' " %(keyword)
self.resql = self.mysqlClass.select_data(self.sql)
if self.resql['state'] != 'E':
for shop in self.resql['alldata']:
if shop['status']==1:
shop['status']="营业中"
else:
shop['status'] = '停止营业'
return {'code':0,'shop_list':self.resql['alldata'],'msg': '获取商铺列表成功'}
else:
return {'code': -1, 'msg': '获取商铺列表失败'}
except Exception as e:
print(e)
return {"code": -1, "data": {"msg": str(e)}}, 500
使用装饰器对需要验证的请求都做了拦截操作
def permission(identifier="any"):
def wrapper(func):
def decorated_view(*args, **kwargs):
if identifier == "any":
return func(*args, **kwargs)
elif identifier == "token":
tokenClass = Token.Token()
token = request.headers['token']
validate_token = tokenClass.validate(token)
validate_code = validate_token["code"]
if validate_code != 1005:
return validate_token
else:
return func(*args, **kwargs)
elif identifier == 'add':
redisClass = Redis.Redis()
parser = reqparse.RequestParser()
parser.add_argument('code', type=str, help='code: type is str')
parser.add_argument('email', type=str, help='email: type is str')
argsd = parser.parse_args()
code = argsd['code']
email = argsd['email']
mailcode = redisClass.get_data('code-'+str(email))
if mailcode == None:
return {'code': -1, 'msg': '验证码失效'}, 200
if mailcode == code:
redisClass.delete('code-'+str(email))
return func(*args, **kwargs)
else:
return {'code':-1,'msg':'验证码错误'},200
else:
return {"code": -1, "msg": "未知错误"}, 200
return decorated_view
return wrapper
因为项目中多处需要使用到mysql,所以就按照自己的习惯封装了一下pymysql。
class MySQL(object):
def __init__(self):
self.jox_dict = Utils.Dict()
self.conn = pymysql.connect(host=mysqlConf['ip'], port=mysqlConf['port'], user=mysqlConf['username'],
password=mysqlConf['passwd'], database=mysqlConf['DB'],cursorclass=pymysql.cursors.DictCursor )
//执行查询sql时调用
def select_data(self, sql):
try:
self.cur = self.conn.cursor()
self.cur.execute(sql)
self.cur.close()
self.alldata = self.cur.fetchall()
except Exception as e:
# 发生错误时回滚,并返回erro
self.conn.rollback()
return {"state":"E","msg":str(e)}
if len(self.alldata) > 0:
self.alldata = self.jox_dict.data_format(self.alldata)
return {"state": "T", "msg": "返回"+str(len(self.alldata))+"条数据" ,"alldata":self.alldata}
else:
return {"state": "F", "msg": "返回"+str(len(self.alldata))+"条数据",'alldata':[]}
//执行插入单条数据或者更新单条数据时调用
def insert_data(self,sql):
try:
self.cur = self.conn.cursor()
# 执行SQL语句
self.cur.execute(sql)
# 提交到数据库执行
self.conn.commit()
return {"state": "T", "msg": str(self.cur)}
except Exception as e:
# 发生错误时回滚,并返回erro
self.conn.rollback()
return {"state": "E", "msg": str(e)}
//执行插入/更新多条数据时调用,第一次调用时conn参数传None即可
def add_insert(self,sql,conn):
try:
if conn =="":
conn = self.conn
self.cur = conn.cursor()
# 执行SQL语句
self.cur.execute(sql)
return {"state": "T", "conn":conn,"cur":self.cur}
except Exception as e:
return {"state": "E", "msg": str(e)}
//调用add_insert后,需要在最后的时候调用commit_inserst,将任务提交到数据库执行
def commit_inserst(self,conn):
try:
# 提交到数据库执行
conn.commit()
return {"state": "T"}
except Exception as e:
# 发生错误时回滚,并返回erro
conn.rollback()
return {"state": "E", "msg": str(e)}
项目中的token、code等缓存数据都存入Redis中,小小的封装了下
class Redis:
def __init__(self):
self.r = redis.StrictRedis(host=redisConf['ip'],password=redisConf['passwd'], port=redisConf['port'] ,db=0)
def set_data(self, key, data, ex=None):
self.r.set(pickle.dumps(key), pickle.dumps(data), ex)
def delete(self,key):
self.r.delete(pickle.dumps(key))
# 将文本流从redis中读取并反序列化,返回
def get_data(self, key):
self.data = self.r.get(pickle.dumps(key))
if self.data is None:
return None
return pickle.loads(self.data)
项目中用到的一些简单的处理方法
//对时间的操作
class Time():
def get_time(self):
st = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
sttotime = datetime.datetime.strptime(st, "%Y-%m-%d %H:%M:%S")
return sttotime
def more_day(self,datetimes):
return datetimes + datetime.timedelta(days=1)
//因为从mysql数据库取出的数据中有可能存在datetime、decimal格式的数据,所以在封装mysql方法的时候直接将数据格式化了
class Dict():
def data_format(self,list):
for data in list:
for key, value in data.items():
if isinstance(value,datetime.datetime):
data[key] = value.strftime("%Y-%m-%d %H:%M:%S")
if isinstance(value,decimal.Decimal):
data[key] = float(value)
return list
自我感觉这个flask的项目还有很多的缺点,欢迎各位dalao指正,github链接:https://github.com/jon-son/msdt 。github中会放vue框架写的前端(前端朋友写的)