Flask项目1(美食地图)

美食地图项目(Flask后台)

一、功能API目录

  1. 用户注册
  2. 邮箱验证码
  3. 用户登录
  4. 获取用户信息
  5. 获取店铺列表
  6. 获取店铺详情
  7. 获取店铺菜单
  8. 获取评论列表
  9. 新增评论
  10. 上传图片

二、项目详解(举例说明,因为流程都一样,就是具体的细节区别而已)

app.py ---->jox_restful/xxx.py ----> jox_api/xxx.py ----> jox_api/Mysql.py or jox_api/Redis.py

1.app.py:项目入口文件,该项目使用flask-restful扩展插件
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)
2.jox_restful: 接收路由请求(下方展示一个示例)

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
3.jox_api: 处理将与数据库交互的数据及拼装返回前端的数据(下方展示一个示例)

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

三、封装的方法类

1.Auth

使用装饰器对需要验证的请求都做了拦截操作

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
2.Mysql

因为项目中多处需要使用到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)}
3.Redis

项目中的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)
4.Utils

项目中用到的一些简单的处理方法

//对时间的操作
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框架写的前端(前端朋友写的)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值