def get_image_code(): """ 获取图片验证码 1.接收请求,获取UUID和上一个uuid 2.判断数据库保存的uuid是否等于last_uuid等于删除, 3.生成图片验证码 4.保存新的uuid,对应的图片文本信息 :return: josnify 验证码图片 """ # 1.接收请求,获取UUID,last_uuid uuid=request.args.get('uuid') last_uuid=request.args.get('last_uuid') if not uuid: #缺省参数报403异常 abort(403) # 2.生成图片验证码 名字,文字信息,图片信息 name, text, image = captcha.generate_captcha() current_app.logger.debug('图片验证码信息:'+text) # 4.删除上次生成的验证码图片 try: if last_uuid: redis_conn.delete('ImageCode:'+last_uuid) # 3.保存UUID对应的验证码文字信息,设置时长 redis_conn.set('ImageCode:' + uuid, text,constants.IMAGE_CODE_REDIS_EXPIRES) except Exception as e: current_app.logger.debug(e) return jsonify(re_code=RET.DBERR,msg='保存图片验证码失败') response=make_response(image) response.headers['Content-Type']='image/jpg' return response
def image_code(image_code_id): """ 获取图片验证码 Args: image_code_id: 图片验证码编号 Retruns: 正常情况(验证码图片) 错误情况(错误信息) """ # 1. 业务逻辑处理 if not image_code_id: return jsonify(errcode=RET.NODATA, errmsg='缺少数据') # 2. 生成验证码图片 name, text, image_data = captcha.generate_captcha() # print(text) # 将验证码真实值与编号保存到redis中, 使用字符串数据存储单条记录: 'image_code_编号': '验证码真实值' try: redis_conn.set('image_code_{}'.format(image_code_id), text, ex=current_app.config.get('IMAGE_CODE_REDIS_EXPIRE')) except Exception as e: # 记录日志 current_app.logger.error(e) return jsonify(errcode=RET.DBERR, errmsg='保存图片验证码失败') # 3. 返回图片 resp = make_response(image_data) resp.headers['Content-Type'] = 'image/jpg' return resp
def get_areas(): """获取城区信息: 1.查询出所有城区信息 2.响应数据 """ # 1.查询所有城区信息 try: resp_json = redis_conn.get("area_info") except Exception as e: current_app.logger.error(e) else: if resp_json: current_app.logger.info("hit redis area_info") return resp_json.decode(), 200, {"Content-Type": "application/json"} try: areas = Area.query.all() except Exception as e: current_app.logger.debug(e) return jsonify(re_code=RET.DBERR, msg='查询城区信息失败') if not areas: return jsonify(re_code=RET.NODATA, msg='暂无城区') areas = [area.to_dict() for area in areas] resp_dict = dict(re_code=RET.OK, msg='查询城区成功', areas=areas) resp_json = json.dumps(resp_dict) try: redis_conn.set("area_info", resp_json, constants.AREA_INFO_REDIS_EXPIRES) except Exception as e: current_app.logger.error(e) return resp_json, 200, {"Content-Type": "application/json"}
def get_hosue_details(): """ 获取房屋详情信息 """ # 接收路径参数 house_id = request.args.get('house_id') if not house_id: return jsonify(errcode=RET.PARAMERR, errmsg="缺少必须参数, 请检查路径是否正确") # 尝试获取访问者的id, 如果获取为空, 将使用默认值'-1'替代 call_user_id = session.get('user_id', '-1') # 尝试从redis中读取缓存数据 try: json_house = redis_conn.get('house_info_{}'.format(house_id)) except Exception as e: current_app.logger.error(e) else: if json_house is not None: return '{{"errcode": "0", "errmsg": "OK", "data": {0}, "call_user_id": {1}}}'.format(json_house.decode(), call_user_id), \ 200, {"Content-Type": "application/json"} # 查询数据库 try: house = House.query.filter_by(id=house_id).first() except Exception as e: current_app.logger.error(e) return jsonify(errcode=RET.DBERR, errmsg="数据库异常") if house is None: return jsonify(errcode=RET.NODATA, errmsg="没有查询到数据") try: # 先将数据转换为字典, 这是在模型中封装的方法 house_data_dict = house.to_full_dict() except Exception as e: current_app.logger.error(e) return jsonify(errcode=RET.SERVERERR, errmsg="数据提取失败, 请联系管理员") else: # 将数据存放到redis中 json_house = json.dumps(house_data_dict) # 获取设置的redis过期时间, 配置文件中 redis_expires = current_app.config.get('HOME_PAGE_DATA_REDIS_EXPIRES') try: redis_conn.set('house_info_{}'.format(house_id), json_house, ex=redis_expires) except Exception as e: current_app.logger.error(e) return jsonify(errcode=RET.DBERR, errmsg="设置缓存异常") # return jsonify(errcode=RET.OK, errmsg="OK", data=house.to_full_dict()) return '{{"errcode": "0", "errmsg": "OK", "data": {0}, "call_user_id": {1}}}'.format( json_house, call_user_id), 200, { "Content-Type": "application/json" }
def get_house_index(): """ 获取主页幻灯片 """ # 设置首页获取首页的幻灯片数量 HOME_PAGE_MAX_IMAGE = 5 # 尝试从缓存中读取 try: json_houses = redis_conn.get('home_page_data') except Exception as e: current_app.logger.error(e) if json_houses is not None: return '{{"errcode": "0", "errmsg": "OK", "data": {}}}'.format( json_houses.decode()), 200, { "Content-Type": "application/json" } else: # 查询数据库 try: houses = House.query.order_by( House.order_count.desc()).limit(HOME_PAGE_MAX_IMAGE).all() except Exception as e: current_app.logger.error(e) return jsonify(errcode=RET.DBERR, errmsg="查询数据库失败") if not houses: return jsonify(errcode=RET.NODATA, errmsg="抱歉, 暂时没有查到数据") houses_list = [] # 遍历house表的查询集 for house in houses: # 如果房屋未设置主图片, 则跳过 if not house.index_image_url: continue houses_list.append(house.to_basic_dict()) # 将数据转换为json, 并保存到redis缓存中, 字符串类型 json_houses = json.dumps(houses_list) # 获取redis缓存时间 home_page_data_redis_expires = current_app.config.get( 'HOME_PAGE_DATA_REDIS_EXPIRES') try: redis_conn.set('home_page_data', json_houses, ex=home_page_data_redis_expires) except Exception as e: current_app.logger.error(e) return '{{"errcode": "0", "errmsg": "OK", "data": {}}}'.format( json_houses), 200, { "Content-Type": "application/json" }
def get_area_info(): """ 获取城区信息 """ # 尝试从redis中读取数据, 如果读取成功则使用缓存返回给前端, 否则从数据库获取 try: resp_json = redis_conn.get('area_info') except Exception as e: current_app.logger.error(e) else: if resp_json is not None: # 代表redis中已经具有缓存数据 current_app.logger.info('hit redis area_info') # 表示拿到了数据, 记录日志 return resp_json, 200, {'Content-Type': 'application/json'} # 查询数据库读取城区信息 try: area_li = Area.query.all() except Exception as e: current_app.logger.error(e) return jsonify(errcode=RET.DBERR, errmsg="数据库异常") area_dict_li = [] # 将对象转为字典 for area in area_li: # 得到每行数据的字段, to_dict是在model里封装的方法 area_dict_li.append(area.to_dict()) # 将返回的数据转换为json字符串 resp_dict = dict(errcode=RET.OK, errmsg='ok', data=area_dict_li) resp_json = json.dumps(resp_dict) # 将数据保存到redis中 try: # 注意这里一定要设置有效期, 否则哪怕数据库的记录更新了, 返回给前端的也是历史记录的缓存 redis_conn.set( 'area_info', resp_json, ex=current_app.config.get('AREA_INFO_REDIS_CACHE_EXPIRES')) except Exception as e: current_app.logger.error(e) return resp_json, 200, {'Content-Type': 'application/json'}
def house_detail(house_id): """房屋详情页面: 1.获取url栏中的house_id 2.根据house_id获取house详细信息 3.判断用户是否登录, 4.响应结果 """ # 1.获取url栏中的house_id # 2.根据house_id获取house详细信息 try: resp_json = redis_conn.get("house_info_{}".format(house_id)) except Exception as e: current_app.logger.error(e) else: if resp_json: current_app.logger.info("hit redis house_info_{}".format(house_id)) return resp_json.decode(), 200, {"Content-Type": "application/json"} try: house = House.query.get(house_id) except Exception as e: current_app.logger.debug(e) return jsonify(re_code=RET.DBERR, msg='查询房屋信息失败') if not house: return jsonify(re_code=RET.NODATA, msg='房屋不存在') house = house.to_full_dict() # 3. 获取user_id : 当用户登录后访问detail.html,就会有user_id,反之,没有user_id login_user_id = session.get('user_id', -1) resp_dict = dict(re_code=RET.OK, msg='查询成功', data={'house': house, 'login_user_id': login_user_id}) resp_json = json.dumps(resp_dict) try: redis_conn.set("house_info_{}".format(house_id), resp_json, constants.AREA_INFO_REDIS_EXPIRES) except Exception as e: current_app.logger.error(e) # 4.响应结果 return resp_json, 200, {"Content-Type": "application/json"}
def get_sms_code(mobile): """ 获取短信验证码 Args: mobile: 注册人的手机号 URL Param: image_code_id: 图片验证码id image_code : 图片验证码 Retruns: 正常情况: 发送成功的json信息 错误情况: 异常的json信息 """ # 1. 业务逻辑处理 # 获取短信验证码的过期时间 sms_code_redis_expire = current_app.config.get('SMS_CODE_REDIS_EXPIRE') if sms_code_redis_expire % 60 != 0: return jsonify(errcode=RET.PARAMERR, errmsg='短信验证码过期时间不合法, 需为60的整除数') # 效验参数是否缺失 image_code_id = request.args.get('image_code_id') image_code = request.args.get('image_code') if not all([mobile, image_code_id, image_code]): return jsonify(errcode=RET.PARAMERR, errmsg='参数不全') # 效验手机号是否合法 res = re.match(r"^1[3456789]\d{9}$", mobile) if res is None: return jsonify(errcode=RET.DATAERR, errmsg='非法数据, 不是合法的手机号') # 效验图片验证码是否正确, 从redis中取出真实的验证码, 与用户输入的值对比 try: real_image_code = redis_conn.get('image_code_{}'.format(image_code_id)) except Exception as e: # 记录错误日志 current_app.logger.error(e) return jsonify(errcode=RET.DBERR, errmsg='读取Redis数据库异常') # 判断图片验证码是否过期 if real_image_code is None: return jsonify(errcode=RET.NODATA, errmsg='图片验证码已失效, 请点击更换重试') # 对比验证码 if real_image_code.decode().lower() != image_code.lower(): # 表示用户填写错误 return jsonify(errcode=RET.DATAERR, errmsg='图片验证码错误') # 删除已经使用的验证码, 防止对同一个验证码进行多次验证 try: redis_conn.delete('image_code_{}'.format(image_code_id)) except Exception as e: # 记录错误日志, 这里只是一个逻辑操作, 不要提前返回 current_app.logger.error(e) # 判断用户在短时间内是否发送过验证码, 如60s内, 如果有发送记录, 则在规定时间内不允许发送第二次 try: send_sign = redis_conn.get('send_sms_code_{}'.format(mobile)) except Exception as e: # 记录错误日志 current_app.logger.error(e) else: if send_sign is not None: # 表示用于在短时间内有发送短信的记录, RET.REQERR = "4201" return jsonify(errcode=RET.REQERR, errmsg='请求次数受限, 请于60秒后发送') # 判断手机号是否已存在, 如果不存在, 则生成短信验证码, 发送短信 try: user = User.query.filter_by(mobile=mobile).first() except Exception as e: # 记录错误日志, 这里不能return终止, 因为可能会出现用户信息正确, 但数据库异常的情况, 此时应该让用户继续注册 current_app.logger.error(e) else: if user is not None: # 表示手机号已存在 return jsonify(errcode=RET.DATAEXIST, errmsg='该手机号已经注册') # 设置短信验证码, 并保存在redis中 sms_code = '{0:0>6}'.format(random.randint(0, 999999)) try: # 在redis保存字符串数据 redis_conn.set('sms_code_{}'.format(mobile), sms_code, ex=sms_code_redis_expire) # 保存发送短信的手机号记录, 防止用户在短时间内(如60s)执行重复发送短信的操作 redis_conn.set('send_sms_code_{}'.format(mobile), 'yes', ex=current_app.config.get('SEND_SMS_CODE_INTERVAL')) except Exception as e: # 记录错误日志 current_app.logger.error(e) return jsonify(errcode=RET.DBERR, errmsg='短信验证码保存异常') # 保存短信验证码到redis中: 手机号(key): 验证码(value) 字符串类型 # ccp = CCP() # result = ccp.sendTemplateSMS(mobile, [sms_code, str(sms_code_redis_expire / 60)], '1') # if result == 0: # # 发送成功 # return jsonify(errcode=RET.OK, errmsg='短信发送成功') # else: # return jsonify(errcode=RET.THIRDERR, errmsg='短信发送失败, 第三方错误') # 使用celery进行异步请求, 发送短信 send_sms.delay(mobile, [sms_code, str(sms_code_redis_expire / 60)], '1') # 因为selery是异步操作的, 它的执行不会对这里产生阻塞, 所以我们设想, 只要发送了, 就代表成功了 return jsonify(errcode=RET.OK, errmsg='短信发送成功')
def send_sms_code(): """发送手机短信息验证码: 1.接收参数,手机号,图片验证码,uuid 2.校验数据 3.判断图片验证码是否正确,如果正确 4.发送短信验证码 """ # 1.接收参数,手机号,图片验证码,uuid json_str=request.data json_dict=json.loads(json_str) phone_num=json_dict.get('phone_num') image_code_client=json_dict.get('image_code') uuid=json_dict.get('uuid') # 2.校验数据 if not all([phone_num,image_code_client,uuid]): return jsonify(re_code=RET.PARAMERR,msg='参数缺少') # 校验手机号是否正确 if not re.match(r'^0\d{2,3}\d{7,8}$|^1[358]\d{9}$|^147\d{8}$',phone_num): return jsonify(re_code=RET.PARAMERR,msg='手机号不正确') #判断用户是否已注册 try: user=User.query.filter(User.phone_num == phone_num).first() except Exception as e: current_app.logger.debug(e) return jsonify(re_code=RET.DBERR,msg='查询数据库错误') #用户存在,提示该账户已被注册 if user: return jsonify(re_code=RET.DATAEXIST,msg='该用户已被注册') # 3.判断图片验证码是否正确,如果正确 try: # 从Redis取出值图片验证码 image_code_server=redis_conn.get('ImageCode:'+uuid) except Exception as e: current_app.logger.debug(e) return jsonify(re_code=RET.DBERR,msg='获取服务器图片验证码失败') #判断为验证码空或者过期 if not image_code_server: return jsonify(re_code=RET.NODATA,msg='验证码已过期') #校验和前端传的验证码是否相等 if image_code_server.lower()!=image_code_client.lower(): return jsonify(re_code=RET.DATAERR,msg='验证码输入有误') # 4.生成验证码 sms_code='%06d' % random.randint(0,99999) current_app.logger.debug('短信验证码为:'+sms_code) # 5.发送短信验证码 验证码 过期时间:容联的时间单位为:分 短信模板1 # result = CCP().send_sms('15770633066',[sms_code,constants.SMS_CODE_REDIS_EXPIRES/60],'1') # if result != 1: # # 短信发送失败 # return jsonify(re_code=RET.THIRDERR,msg='发送短信验证码失败') # 6.发送成功,验证码存储到Redis try: redis_conn.set('PhoneCode:'+phone_num,sms_code,constants.SMS_CODE_REDIS_EXPIRES) except Exception as e: current_app.logger.debug(e) return jsonify(re_code=RET.DBERR,msg='存储短信验证码失败') #响应结果 return jsonify(re_code=RET.OK,msg='验证码发送成功')
def send_sms_code(): """发送手机短信息验证码: 1.接收参数,手机号,图片验证码,uuid 2.校验数据 3.判断图片验证码是否正确,如果正确 4.发送短信验证码 """ # 接收参数,手机号,图片验证码,uuid json_str = request.data json_dict = json.loads(json_str) phone_num = json_dict.get('phone_num') image_code_client = json_dict.get('image_code') uuid = json_dict.get('uuid') # 校验数据 if not all([phone_num, image_code_client, uuid]): return jsonify(re_code=RET.PARAMERR, msg='参数缺少') # 校验手机号是否正确 if not re.match( r'^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$', phone_num): return jsonify(re_code=RET.PARAMERR, msg='手机号不正确') # 判断用户是否已注册 try: user = User.query.filter(User.phone_num == phone_num).first() except Exception as e: current_app.logger.debug(e) return jsonify(re_code=RET.DBERR, msg='查询数据库错误') # 用户存在,提示该账户已被注册 if user: return jsonify(re_code=RET.DATAEXIST, msg='该用户已被注册') # 判断图片验证码是否正确,如果正确 try: # 从Redis取出值图片验证码 image_code_server = redis_conn.get('ImageCode:' + uuid) except Exception as e: current_app.logger.debug(e) return jsonify(re_code=RET.DBERR, msg='获取服务器图片验证码失败') # 判断为验证码空或者过期 if not image_code_server: return jsonify(re_code=RET.NODATA, msg='验证码已过期') # 校验和前端传的验证码是否相等 if image_code_server.decode().lower() != image_code_client.lower(): return jsonify(re_code=RET.DATAERR, msg='验证码输入有误') # 4.生成验证码 sms_code = '%06d' % random.randint(0, 99999) current_app.logger.debug('短信验证码为:' + sms_code) # 5.发送短信验证码 验证码 # 后台设置 # 同一个手机号同一个验证码模板,每30秒只能获取1条 # 同一个手机号验证码类内容,每小时最多能获取3条 # 同一个手机号验证码类内容,24小时内最多能获取到10条 # result = SendSMS().send_sms(phone_num, sms_code) # if not result: # # 短信发送失败 # return jsonify(re_code=RET.THIRDERR, msg='发送短信验证码失败') # 6.发送成功,验证码存储到Redis try: redis_conn.set('PhoneCode:' + phone_num, sms_code, constants.SMS_CODE_REDIS_EXPIRES) except Exception as e: current_app.logger.debug(e) return jsonify(re_code=RET.DBERR, msg='存储短信验证码失败') # 响应结果 return jsonify(re_code=RET.OK, msg='验证码发送成功')