Example #1
0
def login():
    logging = Use_Loggin()
    # 参数提取
    reqs_dice = request.get_json()
    mobile = reqs_dice.get("mobile")
    pwd = reqs_dice.get("password")

    # 参数校验
    if not all([mobile, pwd]):
        return jsonify(error_num=RET.PARAMERR, errmsg="参数不完整")

    mobile_re = re.match(r'1[34578]\d{9}', mobile)
    if mobile_re == None:
        return jsonify(error_num=RET.PARAMERR, errmsg="手机号格式错误")

    # 判断错误次数, 保存到redis中, 时间限制
    try:
        user_ip = request.remote_addr
        # "access_nums_ip地址": "次数"
        access_conut = redis_store.get("access_nums_%s" % user_ip)
    except Exception as e:
        logging.warning("警告: redis查询用户ip地址次数错误, 这里不限制访问, 让用户继续访问")
    else:
        if access_conut != None:
            if int(access_conut.decode(
                    'utf-8')) >= constants.LOGIN_MUNS_COUNTS:
                return jsonify(error_num=RET.REQERR, errmsg="请求次数过于频繁")
        else:
            pass

    # 比对数据库账号密码
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except:
        logging.error("错误: 数据库查询错误")
        return jsonify(error_num=RET.DATAERR, errmsg="获取用户信息失败")

    # 如果输入错误, 记录错误次数, 次数过多, 封ip
    if user is None or not user.check_pwd(pwd):  # 如果找不到用户 or 密码  返回错误信息
        try:
            # 额外配置, 错误后计数访问主机的ip地址
            redis_store.incr("access_nums_%s" % user_ip, amount=1)
            redis_store.expire("access_nums_%s" % user_ip,
                               time=constants.LOGIN_MUNS_NOTIME)
        except:
            pass
        # 因为用户名或者密码错误, 这里直接返回错误信息
        return jsonify(error_num=RET.NODATA, errmsg="用户名或密码不存在")

    # 验证成功
    from flask import session
    session["name"] = user.name
    session["mobile"] = user.mobile
    session["user_id"] = user.id

    return jsonify(errno=RET.OK, errms="登录成功")
Example #2
0
def order_pay(order_id):
	logging = Use_Loggin()
	user_id = g.user_id
	
	# 判断订单状态: 存在, 在字符
	try:
		orders = Order.query.filter(Order.id == order_id,
		                            Order.user_id == user_id,
		                            Order.status=="WAIT_PAYMENT").first()
		sun_amonut = str(orders.amount/100.0)  # 总金额
		
	except Exception as e:
		logging.error("订单数据查询失败")
		return jsonify(errno=RET.DBERR, errmsg="订单-数据库异常2")
	
	if orders is None:
		return jsonify(errno=RET.NODATA, errmsg="订单-订单数据有误")
	
	# 路径拼接
	BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
	alipay_public_key_path = os.path.join(os.path.join(BASE_DIR, "keys_pay"), 'alipay_public_key.pem')
	app_private_key_path = os.path.join(os.path.join(BASE_DIR, "keys_pay"),   'app_private_key.pem')

	# 读取密钥数据
	with open(alipay_public_key_path, "r", encoding="utf-8") as f:
		alipay_public_key_path_read = f.read()
	
	with open(app_private_key_path, "r", encoding="utf-8") as f:
		app_private_key_path_read = f.read()
	
	
	# 初始化阿里与支付模块
	alipay_client = AliPay(appid=constants.ALIPAY_APIT_NUMS,                      # 沙箱环境的apid
	                       app_notify_url=None,                                   # 回调, 不需要回调
	                       app_private_key_string=app_private_key_path_read,      # 给路径即可
	                       alipay_public_key_string=alipay_public_key_path_read,
	                       sign_type="RSA2",                                      # RSA或者 RSA2
	                       debug=False)                                           # 默认

	# 手机网站支付 需要跳转到 https://openapi.alipaydev.com/gateway.do + order_string
	order_string = alipay_client.api_alipay_trade_wap_pay(
		subject=u"爱家租房 %s" % order_id,  # 标题
		out_trade_no=order_id,             # 订单的编号
		total_amount=sun_amonut,           # 总金额
		return_url="http://127.0.0.1:5000/ordersComplete.html",  # 返回的链接地址
		notify_url=None,
	)
	
	# 构建用户跳转的支付宝链接地址
	pay_url = constants.ALIPAY_URL_DEV_PRIFIX + order_string
	
	# 把链接发给前端
	return jsonify(errno=RET.OK, errmsg="OK", data={"pay_url": pay_url})
Example #3
0
def save_house_img():
    logging = Use_Loggin()

    # 获取参数
    # <input type="file" accept="image/*" name="house_image" id="house-image">
    # <input type="hidden" name="house_id" id="house-id" value="">
    raw_image_file = request.files.get("house_image")
    house_id = request.form.get("house_id")

    # 校验
    if not all([raw_image_file, house_id]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不完整1")

    # 判断house_id正确性
    try:
        house = House.query.get(house_id)
    except Exception as e:
        return jsonify(errno=RET.NODATA, errmsg="数据库查询房屋id失败, 请稍后再试")

    if house_id is None:
        return jsonify(errno=RET.NODATA, errmsg="房屋id不存在")

    image_data = raw_image_file.read()
    try:
        from ihome.utils.updown_image.seven_ox_coludy import down_load_of_Binary
        house_image_name = down_load_of_Binary(image_data)
    except Exception as e:
        logging.error("七牛云图片上传失败")
        return jsonify(errno=RET.THIRDERR, errmsg="上传失败3")

    # 保存数据
    house_image = HouseImage(house_id=house_id, url=house_image_name)
    db.session.add(house_image)

    # 处理房屋的主图片
    '''
	在第一次保存时, 设置了主图片为保存图片
	如果是多次设置, 应该重写写接口设置为主图片 ?
	'''
    if house.index_image_url is None or not house.index_image_url:
        house.index_image_url = house_image_name
        db.session.add(house)

    try:
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        logging.error("数据库保存房屋图片信息异常")
        return jsonify(errno=RET.DATAERR, errmsg="数据库保存失败")

    image_url = constants.URL_OF_QINIU_IMAGE_PREFIX + house_image_name
    return jsonify(errno=RET.OK, errmsg="OK", data={"image_url": image_url})
Example #4
0
def save_order_comment(order_id):
    logging = Use_Loggin()
    user_id = g.user_id

    # 获取参数
    req_data = request.get_json()
    comment = req_data.get("comment")  # 评价信息

    # 检查参数
    if not comment:
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    try:
        # 需要确保只能评论自己下的订单,而且订单处于待评价状态才可以
        order = Order.query.filter(Order.id == order_id,
                                   Order.user_id == user_id,
                                   Order.status == "WAIT_COMMENT").first()
        house = order.house
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="无法获取订单数据")

    if not order:
        return jsonify(errno=RET.REQERR, errmsg="操作无效")

    try:
        # 将订单的状态设置为已完成
        order.status = "COMPLETE"
        # 保存订单的评价信息
        order.comment = comment
        # 将房屋的完成订单数增加1
        house.order_count += 1

        db.session.add(order)
        db.session.add(house)
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        logging.error("数据库保存用户订单, 保存评价信息, 房屋订单数增加保存失败-220")
        return jsonify(errno=RET.DBERR, errmsg="操作失败")

    # 因为房屋详情中有订单的评价信息,为了让最新的评价信息展示在房屋详情中,所以删除Redis中关于本订单房屋的详情缓存
    try:
        redis_store.delete("house_info_%s" % order.house.id)
    except Exception as e:
        current_app.logger.error(e)

    return jsonify(errno=RET.OK, errmsg="OK")
Example #5
0
def get_user_house():
    logging = Use_Loggin()
    user_id = g.user_id
    try:
        user = User.query.get(user_id)
        houses = user.houses
    except Exception as e:
        logging.error("数据库查询房东信息错误1")
        return jsonify(errno=RET.DBERR, errmsg="获取数据失败")

    # 将查询到的数据转成dict放到list中
    houses_li = list()
    if houses:
        for house in houses:
            houses_li.append(house.to_base_dict())  # 数据库的基本信息
    return jsonify(errno=RET.OK, errmsg="OK", data={"houses": houses_li})
Example #6
0
def accept_reject_order(order_id):
    logging = Use_Loggin()
    user_id = g.user_id

    # 获取参数
    req_data = request.get_json()
    if not req_data:
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    # action参数表明客户端请求的是接单还是拒单的行为
    action = req_data.get("action")
    if action not in ("accept", "reject"):
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    try:
        # 根据订单号查询订单,并且要求订单处于等待接单状态
        order = Order.query.filter(Order.id == order_id,
                                   Order.status == "WAIT_ACCEPT").first()
        house = order.house
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="无法获取订单数据")

    # 确保房东只能修改属于自己房子的订单
    if not order or house.user_id != user_id:
        return jsonify(errno=RET.REQERR, errmsg="操作无效")

    if action == "accept":
        # 接单,将订单状态设置为等待评论
        order.status = "WAIT_PAYMENT"
    elif action == "reject":
        # 拒单,要求用户传递拒单原因
        reason = req_data.get("reason")
        if not reason:
            return jsonify(errno=RET.PARAMERR, errmsg="参数错误")
        order.status = "REJECTED"
        order.comment = reason

    try:
        db.session.add(order)
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        logging.error("拒接接单-数据库保存错误180")
        return jsonify(errno=RET.DBERR, errmsg="操作失败")

    return jsonify(errno=RET.OK, errmsg="OK")
Example #7
0
    def sendTemplateSMS(self, to, datas, tempId):
        try:
            result = self.rest.sendTemplateSMS(to, datas, tempId)
        except Exception as e:
            try:
                from ihome.utils.use_logging import Use_Loggin
                logg = Use_Loggin()
                logg.error(e)
                logg.error("短信发送错误, 请查看Send_Temp模块是否有误")
            except:
                print("logg模块导入错误, 请查看是否有误")

            raise e
        success = "<statusCode>000000</statusCode>"
        if success in result:
            return True
        else:
            return False
Example #8
0
def set_user_name():
	logging = Use_Loggin()
	# 获取参数
	user_id = g.user_id  # 能够登录装饰器, 说明一定有用户名, 就不验证了
	reqs_data = request.get_json()
	
	if not reqs_data:
		return jsonify(errno=RET.NODATA, errmsg="参数不完整")
	
	row_user_name = reqs_data.get("name")
	if not row_user_name:
		return jsonify(errno=RET.NODATA, errmsg="名字未输入")
	
	# 用户名长度限制
	if len(str(row_user_name)) > constants.USER_SET_NAME_LENG:
		return jsonify(errno=RET.PARAMERR, errmsg="用户名过长")
	
	# 校验参数, 用户名限制在字数以内, 不得使用特殊符号
	for i in constants.USER_SET_NAME_NOT_INCLUDE:
		if i in row_user_name:
			booler = False
			break
		else:
			booler = True

	if booler is False:
		return jsonify(errno=RET.PARAMERR, errmsg="用户不得包含特殊字符")
	
	# 保存用户昵称name,并同时判断name是否重复(利用数据库的唯一索引)
	from ihome import db
	try:
		User.query.filter_by(id=user_id).update({"name": row_user_name})
		#  name = db.Column(db.String(32), unique=True, nullable=False)  # 用户暱称
		db.session.commit()
	except Exception as e:
		db.session.rollback()
		logging.error("用户保存用户名失败, 数据库更新失败")
		return jsonify(errno=RET.DBERR, errmsg="数据库设置用户名失败")
	
	session["name"] = row_user_name
	
	# 返回修改结果
	return jsonify(errno=RET.OK, errmsg="修改成功", data={"name": row_user_name})
Example #9
0
def set_use_avatar():
	logging = Use_Loggin()
	# 获取用户参数: 用户id() 图片(多媒体表单, 二进制)
	user_id = g.user_id  # 装饰器代码中已经将user_id保存在g对象, 所以视图可以直接读取
	
	# 获取图片
	row_image_file = request.files.get("avatar")
	if row_image_file is None:
		return jsonify(errno=RET.PARAMERR, errmsg="未上传图片")
	image_data = row_image_file.read()
	
	# 调用七牛云平台上传图片
	try:
		# 正常应该返回文件名
		image_file_name = down_load_of_Binary(image_data)
	except Exception as e:
		logging.error(e)
		return jsonify(errno=RET.THIRDERR, errmsg="上传服务器失败2")
	
	# http://www.mylady.top/static/note_flask --第21节
	'''
	In [31]: User.query.all()
	Out[31]: [User object: name=ying, User object: name=chen, User object: name=zhou]
	​
	In [32]: User.query.filter_by(name='chen').update({'name':'cheng'})
	Out[32]: 1
	​
	In [33]: User.query.all()
	Out[33]: [User object: name=ying, User object: name=cheng, User object: name=zhou]
	'''
	from ihome import db
	try:
		User.query.filter_by(id=user_id).update({"avatar_url": image_file_name})
		db.session.commit()
	except Exception as e:
		db.session.rollback()  # 回滚
		logging.error(e)
		return jsonify(errno=RET.DATAERR, errmsg="数据库保存用户图片url地址失败")
	
	# 成功
	from ihome.constants import URL_OF_QINIU_IMAGE_PREFIX
	http_image_url = str(URL_OF_QINIU_IMAGE_PREFIX + image_file_name)  # 拼接为完整图片url地址
	return jsonify(errno=RET.OK, errmsg="图上保存成功", data={"image_file_name": http_image_url})
Example #10
0
def get_house_info():
    logging = Use_Loggin()
    # 尝试从缓存中读取
    try:
        req_data = redis_store.get("home_page_data")
    except Exception as e:
        logging.error("redis获取index缓存数据错误")
        req_data = None

    if req_data:
        logging.info("hit index page redis")
        # logging.info(req_data.decode("utf-8"))
        req_data = req_data.decode("utf-8")
        req = '{"errno":0, "errmsg":"OK", "data":%s}' % req_data, 200, {
            "Content-Type": "application/json"
        }
        print("req /house/index:", req)
        print("req type(req): ", type(req))
        return req

    else:
        pass

    # redis没有数据, 数据库读取
    try:
        # 返回房屋订单数目最多的5条数据
        houses = House.query.order_by(House.order_count.desc()).limit(
            constants.HOME_PAGE_MAX_HOUSES)
    except Exception as e:
        logging.error("数据库--查询房屋订单数失败")
        return jsonify(errno=RET.DBERR, errmsg="查询失败")

    if not houses:
        return jsonify(errno=RET.NODATA, errmsg="没有数据")

    # 有多个房源信息, 用list作为容器,
    house_img_li = list()
    for house in houses:
        # logging.info(house.to_base_dict())
        # {'house_id': 4, 'title': '123',
        # 'price': 12300, 'area_name': '海淀区', 'img_url': '',
        # 'room_count': 123, 'order_count': 0, 'address': '123',
        # 'user_avatar': 'http://qbg25zlw0.bkt.clouddn.com/FnNBWGcBkB9G3UamXjtfqnnD9lFM',
        # 'ctime': '2020-06-08'}
        house_img_li.append(house.to_base_dict())

    # 将数据转成json(耗时), 并保存到redis
    json_houses = json.dumps(house_img_li)  # '[{}, {}, {}]'
    try:
        redis_store.setex("home_page_data",
                          value=json_houses,
                          time=constants.HOME_PATH_REDIS_CACHE_EXPIRES)
    except Exception as e:
        logging.error("redis保存缓存失败")

    # return jsonify(errno=RET.OK, errmsg="OK", data={"data":json_houses}) 耗时
    req2 = '{"errno"=0, "errmsg"="OK", "data":%s}' % json_houses, 200, {
        "Content-Type": "application/json"
    }
    return req2
Example #11
0
def ger_area_info():
    logging = Use_Loggin()
    # 尝试从redis读取数据
    try:
        resp_json = redis_store.get("area_info")
    except Exception as e:
        logging.error(e)
    else:
        if resp_json is not None:
            logging.info("hit redis: redis有地区数据")
            return resp_json, 200, {"Content-Type": "application/json"}
        else:
            pass

    # 获取城区信息, 不需要前端的参数, 查询数据库
    try:
        areas_li = Area.query.all()
    except Exception as e:
        logging.error("数据库错误")
        return jsonify(errno=RET.DBERR, errmsg="城区-数据库查询错误")

    area_dict_li = list()
    for area in areas_li:
        area_dict_li.append(area.to_dict())

    # 转换成json字符串, 将数据保存到redis中, 整体存取
    res_dict = dict(errno=RET.OK, errmsg="OK", data=area_dict_li)
    resp_json = json.dumps(res_dict)

    # 保存到redis
    try:
        from ihome import constants
        redis_store.setex("area_info",
                          value=resp_json,
                          time=constants.EREA_INFO_CACHE_EXPIRES)
    except Exception as e:
        logging.warning("警告: json保存redis失败, 跳过")

    return resp_json, 200, {"Content-Type": "application/json"}
Example #12
0
def save_order_payment_result():
	"""保存订单支付结果"""
	logging = Use_Loggin()
	alipay_dict = request.form.to_dict()
	
	# 对支付宝的数据进行分离  提取出支付宝的签名参数sign 和剩下的其他数据
	alipay_signAture = alipay_dict.pop("sign")  # 计算结果是很长的字符串
	
	# 路径拼接
	BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
	alipay_public_key_path = os.path.join(os.path.join(BASE_DIR, "keys_pay"), 'alipay_public_key.pem')
	app_private_key_path = os.path.join(os.path.join(BASE_DIR, "keys_pay"),   'app_private_key.pem')
	
	# 读取密钥数据
	with open(alipay_public_key_path, "r", encoding="utf-8") as f:
		alipay_public_key_path_read = f.read()
	
	with open(app_private_key_path, "r", encoding="utf-8") as f:
		app_private_key_path_read = f.read()
	
	# 初始化 SDK工具对象
	try:
		alipay_client = AliPay(appid=constants.ALIPAY_APIT_NUMS,
		                       app_notify_url=None,  # 默认回调url
		                       app_private_key_string=app_private_key_path_read,      # 私钥
		                       alipay_public_key_string=alipay_public_key_path_read,  # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
		                       sign_type="RSA2",     # RSA 或者 RSA2
		                       debug=False)          # 默认False
	except Exception as e:
		logging.error("112行, 订单信息回调信息获取失败, 请管理员注意")
		return jsonify(errno=RET.THIRDERR, errmsg="订单信息回调失败")
	
	# 借助工具验证参数的合法性
	# 如果确定参数是支付宝的,返回True,否则返回false
	try:
		result = alipay_client.verify(alipay_dict, alipay_signAture)
	except Exception as e:
		logging.error("支付回调失败")
		result = False
		return jsonify(errno=RET.THIRDERR, errmsg="支付错误")
		
	if result:
		# 修改数据库的订单状态信息
		order_id = alipay_dict.get("out_trade_no")
		trade_no = alipay_dict.get("trade_no")      # 支付宝的交易号
		# order_id trade_no:  9 2020061822001403580501092285
		try:                                                    # WAIT_COMMENT
			Order.query.filter_by(id=order_id).update({"status": "WAIT_COMMENT", "trade_no": trade_no})
			db.session.commit()
		except Exception as e:
			logging.error("逻辑区提取数据失败")
			db.session.rollback()

	return jsonify(errno=RET.OK, errmsg="OK")
Example #13
0
def get_msm_code(msg_code_phone):
	logg = Use_Loggin()         # 获取日志对象
	# 获取参数
	phone_nums = msg_code_phone                          # 获取: 手机号这个参数
	image_code = request.args.get("image_code")          # 获取: 验证码真实值
	image_code_id = request.args.get("image_code_id")    # 获取: 验证码对应的图片, 需要及时删除 Js生成的UUID

	# 校验数据
	if not all([image_code, image_code_id]):
		return jsonify(error_num=RET.DATAERR, errmsg="参数不完整")

	# 从redis取出 真实的图片value
	from ihome.utils.response_code import RET
	try:
		real_image_code = redis_store.get("image_code_%s" % image_code_id)

	except Exception as e:
		logg.error("错误, 短信验证--redis_store.get(image_code_ image_code_id)提取信息错误")
		return jsonify(error_num=RET.DBERR, errmsg="Redis 数据库异常")

	if real_image_code is None:
		return jsonify(error_num=RET.NODATA, errmsg="Redis 没有验证码信息")

	# -------------判断验证码值是否正确-------------
	# print("real_image_code: ", real_image_code, "  real_image_code.lower(): ", real_image_code.lower().decode('utf-8'))
	# print("image_code: ", image_code, "  image_code.lower(): ", image_code.lower())
	# print(type(real_image_code.lower()))

	# -存在撞库风险, 如果在之后删除redis数据,
	# 为什么选择这里 ?
	try:
		redis_store.delete("image_code_%s" % image_code_id)
	except Exception as e:
		logg.warning("警告: Redis删除验证码图片失败 (非主要错误) , ")
		logg.warning(e)

	if real_image_code.lower().decode('utf-8') != image_code.lower():
		return jsonify(error_num=RET.DBERR, errmsg="图片验证码错误")

	# 判断对于手机号操作, 60s之内不允许操作
	try:
		second_info = redis_store.get("def_sms_code_%s" % phone_nums)
	except Exception as e:
		pass
	else:
		if second_info is not None:
			return jsonify(error_num=RET.REQERR, errmsg="请求频繁")

	# 手机号是否存在
	try:
		user = User.query.filter_by(mobile=phone_nums).first()
	except Exception as e:
		user = None
		logg.error("注册时, 数据库手机号查询错误")

	else:
		if user is not None:
			return jsonify(error_num=RET.DATAEXIST, errmsg="注册手机已存在")

	# 返回短信验证码, 保存在 redis中
	from random import randint
	sms_code = "%06d" % randint(0, 999999)  # 发送的验证码真实值
	try:
		# 有效期
		from ihome.constants import MSG_CODE_REDIS_EXPIES  # 保存到 redis的验证码值
		redis_store.setex("sms_code_%s" % phone_nums, value=sms_code, time=MSG_CODE_REDIS_EXPIES)

		# 保存60s设置, 防止60s内再次触发发送短信的请求
		redis_store.setex("def_sms_code_%s" % phone_nums, value="1", time=MSG_CODE_LONG_EXPIES)

	except Exception as e:
		logg.error("注册时, 保存短信验证码异常1")
		logg.error(e)
		return jsonify(error_num=RET.DBERR, errmsg="Redis 保存短信验证码异常")
	
	# 异步发送短信 windows不支持 celery ?
	# try:
	# 	from ihome.task.sms_send_tasks import send_sms
	# 	send_sms.delay(phone_nums,
	# 	               [sms_code,
	# 	                int(MSG_CODE_REDIS_EXPIES / 60)],
	# 	               1)
	# 	return jsonify(error_num=RET.OK, errmsg="短信发送成功")
	# except Exception as e:
	# 	logg.error("异步发送邮件失败, 使用同步发送邮件")
	
	# 同步发送邮件
	try:
		from ihome.constants import MSG_CODE_REDIS_EXPIES  # 提取配置文件的设置
		from ihome.libs.Send_SMS.Demo_Send import CCP
		ccp = CCP.instance()
		res = ccp.sendTemplateSMS(phone_nums, [sms_code, int(MSG_CODE_REDIS_EXPIES/60)], 1)  # 5是有效期, 1是模板
	
	except Exception as e:
		logg.error("注册时, 保存短信验证码异常2")
		logg.error(e)
		return jsonify(error_num=RET.DBERR, errmsg="保存短信验证码异常")

	if res:
		# 发送成功
		return jsonify(error_num=RET.OK, errmsg="短信发送成功")
	else:
		return jsonify(error_num=RET.THIRDERR, errmsg="短信发送失败")
Example #14
0
def save_order():
    logging = Use_Loggin()
    user_id = g.user_id

    # 获取参数
    order_data = request.get_json()
    if not order_data:
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    house_id = order_data.get("house_id")  # 预订的房屋编号
    start_date_str = order_data.get("start_date")  # 预订的起始时间
    end_date_str = order_data.get("end_date")  # 预订的结束时间
    print("house_id, start_date_str, end_date_str: ", house_id, start_date_str,
          end_date_str)

    # 检查参数是否都有
    if not all((house_id, start_date_str, end_date_str)):
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    # 日期格式检查
    try:
        # 将请求的时间参数字符串转换为datetime类型
        start_date = datetime.strptime(start_date_str, "%Y-%m-%d")
        end_date = datetime.strptime(end_date_str, "%Y-%m-%d")
        assert start_date <= end_date

        # 计算预订的天数
        days = (end_date - start_date).days + 1  # datetime.timedelta
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg="日期格式错误")

    # 查询房屋是否存在
    try:
        house = House.query.get(house_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="获取房屋信息失败")
    if not house:
        return jsonify(errno=RET.NODATA, errmsg="房屋不存在")

    # 预订的房屋是否是房东自己的
    if user_id == house.user_id:
        return jsonify(errno=RET.ROLEERR, errmsg="不能预订自己的房屋")

    print("user_id: ", user_id)
    # 确保用户预订的时间内,房屋没有被别人下单
    try:
        # 查询时间冲突的订单数
        count = Order.query.filter(Order.house_id == house_id,
                                   Order.begin_date <= end_date,
                                   Order.end_date >= start_date).count()
        #  select count(*) from order where ....
    except Exception as e:
        logging.error("数据库查询Order订单失败5")
        return jsonify(errno=RET.DBERR, errmsg="检查出错,请稍候重试")

    if count > 0:
        return jsonify(errno=RET.DATAERR, errmsg="房屋已被预订")

    # 订单总额
    amount = days * house.price
    print("amount: ", amount)

    # 保存订单数据
    order = Order(house_id=house_id,
                  user_id=user_id,
                  begin_date=start_date,
                  end_date=end_date,
                  days=days,
                  house_price=house.price,
                  amount=amount)

    try:
        db.session.add(order)
        db.session.commit()
    except Exception as e:
        logging.error("订单数据-数据库保存失败3")
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg="保存订单失败")

    print("订单保存ok")
    return jsonify(errno=RET.OK, errmsg="OK", data={"order_id": order.id})
Example #15
0
def register():
    logging = Use_Loggin()
    """
	请求参数: 1. 手机号
			 2. 短信验证码
			 3. 密码, 确认密码
	参数格式: json
	:return:
	"""
    from flask import request
    req_dict = request.get_json()  # 获取请求的json, 返回字典
    mobile = req_dict.get("mobile")
    sms_code = req_dict.get("sms_code")
    password = req_dict.get("password")
    password2 = req_dict.get("password2")

    # 校验参数
    if not all([mobile, sms_code, password, password2]):
        return jsonify(error_num=RET.PARAMERR, errmsg="数据不完整")

    # 校验手机格式
    if not re.match(r"1[34578]\d{9}", mobile):
        return jsonify(error_num=RET.PARAMERR, errmsg="手机格式不正确")
    # 校验密码
    if password != password2:
        return jsonify(error_num=RET.PARAMERR, errmsg="两次输入密码不一致")

    # 业务逻辑处理, 从 redis取出短信验证码
    try:
        # 注意: 从redis提取的数据属于 bytes类型, 需要decode
        real_sms_txt = redis_store.get("sms_code_%s" % mobile)

    except Exception as e:
        logging.error("redis数据读取错误")
        logging.error(e)
        return jsonify(error_num=RET.PARAMERR, errmsg="读取真实短信验证码异常")

    # 判断短信验证码是否过期
    if real_sms_txt is None:
        return jsonify(error_num=RET.NODATA, errmsg="短信验证码过期")

    if constants.MSG_CODE_True_OR_False is False:
        # 删除redis中的短信验证码, 防止校验失败后的重复校验 这里我不删除, 短信可以重复利用
        try:
            redis_store.delete("sms_code_%s" % mobile)
        except Exception as e:
            logging.error("短信验证码删除失败")
            logging.error(e)

    # 判断用户填写的短信验证码的正确性
    # print("->"*10, type(real_sms_txt), real_sms_txt, type(sms_code), sms_code)
    # <class 'bytes'> b'075857' <class 'str'> 075857
    if real_sms_txt.decode("utf-8") != sms_code:
        return jsonify(error_num=RET.DATAERR, errmsg="短信验证码错误")

    # 判断手机号是否注册过
    # 手机号是否存在
    from ihome.models import User
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        logging.error("注册时, 数据库手机号查询错误")
        logging.error(e)
        return jsonify(error_num=RET.DATAERR, errmsg="数据库查询是否重复手机号时异常")
    else:
        if user != None:
            return jsonify(error_num=RET.DATAEXIST, errmsg="注册手机已存在")

    # 保存到数据库中
    # 加密处理
    user = User(name=mobile, mobile=mobile)
    # user.generate_password_hash(password)
    user.password = password  # 设置值
    # print(user.password())   # 读取值--设置了报错

    try:
        db.session.add(user)
        db.session.commit()  # 数据正式保存
    except IntegrityError as e:
        db.session.rollback()  # 数据库操作错误的回滚
        logging.error(e)
        logging.error("手机号出现重复值, 用户已经注册")
        return jsonify(error_num=RET.DATAEXIST, errmsg="手机号出现重复值")
    except Exception as e:
        logging.error(e)
        logging.error("数据库出现了问题")
        return jsonify(error_num=RET.DATAEXIST, errmsg="查询数据库异常")

    # 保存登录状态到session中
    from flask import session  # 从flask中导入全局的请求上下文
    session["name"] = mobile
    session["mobile"] = mobile
    session["user_id"] = user.id
    return jsonify(errno=RET.OK, errmsg="用户注册成功")
Example #16
0
def get_house_detail(house_id):
    """
	前端在房屋详情页面展示时,如果浏览页面的用户不是该房屋的房东,则展示预定按钮,否则不展示
	"""
    logging = Use_Loggin()
    # 尝试获取用户登录的信息,若登录,则返回给前端登录用户的user_id,否则返回user_id=-1
    user_id = session.get("user_id", "-1")
    if not house_id:
        return jsonify(errno=RET.PARAMERR, errmsg="参数缺失")

    # 从redis提取数据
    try:
        ret = redis_store.get("house_info_%s" % house_id)
    except Exception as e:
        ret = None
        logging.warning(e)

    if ret:
        logging.info("hit house info redis")
        ret = ret.decode("utf-8")
        resp = '{"errno":0, errmsg:"OK", "data":{"user_id":%s, "house":%s}}' % (
            user_id, ret), 200, {
                "Content-Type": "application/json"
            }
        return resp

    # 如果redis没有数据, 查询数据库--用户未登录也会使用sql查询
    try:
        house = House.query.get(house_id)  # 查询是不是房东在访问
        logging.info("缓存无数据, 从sql中提取")
    except Exception as e:
        logging.error("数据库查询用户登录信息错误")
        return jsonify(errno=RET.DBERR, errmsg="查询错误")

    if not house:
        return jsonify(errno=RET.NODATA, errmsg="数据不存在")

    try:
        house_data = house.full_info_dict()
    except Exception as e:
        logging.error("数据库查询失败2")
        return jsonify(errno=RET.DATAERR, errmsg="查询错误2")

    json_house = json.dumps(house_data)
    try:
        redis_store.setex("house_info_%s" % user_id,
                          value=json_house,
                          time=constants.HOUSE_DETAIL_REDIS_CACHE_EXPIRES)
    except Exception as e:
        logging.error("Reids保存缓存错误")

    test_li = list()
    for i in range(25):
        a = {"%s" % i: "%s" % i}
        test_li.append(a)

    test_json = json.dumps(test_li)
    resp2 = '{"errno":"0", "errmsg":"OK", "data":{"user_id":%s, "house":%s, "test_json":%s}}' % (
        user_id, json_house, test_json), 200, {
            "Content-Type": "application/json"
        }
    return resp2  # 返回信息
Example #17
0
def search_house():
    logging = Use_Loggin()

    # 获取参数, 可有可无
    # http://127.0.0.1:5000/search.html?aid=1&aname=%E4%B8%9C%E5%9F%8E%E5%8C%BA&sd=2020-06-23&ed=2020-07-25
    start_date = request.args.get(key="sd",
                                  default="")  # 用户想要的起始时间  sd=2020-06-23
    end_date = request.args.get(key="ed",
                                default="")  # 结束时间          ed=2020-07-25
    area_id = request.args.get(key="aid",
                               default="")  # 区域编号          aname=东城区
    sort_key = request.args.get(key="ks", default="new")  # 排序关键字
    page = request.args.get(key="p", default="")  # 页数

    # print("1 start_date: ", start_date, type(start_date))   for test
    # print("1 end_date: ", end_date, type(end_date))         for test
    # print("1 area_id: ", area_id, type(area_id))            for test
    # print("1 sort_key: ", sort_key, type(sort_key))         for test
    # print("1 page: ",page , type(page))                     for test

    # 因为参数可传可不传, 所以这里参数校验没必要

    # try:
    # 	if start_date is not None:
    # 		start_date = datetime.strftime(start_date, "%Y-%m-%d")
    # 		print("start_date 2: ", start_date)
    # 	if end_date is not None:
    # 		end_date = datetime.strftime(end_date, "%Y-%m-%d")
    # 		print("end_date 2: ", end_date)
    #
    # 	if start_date and end_date  is not None:
    # 		assert end_date <= start_date
    #
    # except Exception as e:
    # 	return jsonify(errno=RET.PARAMERR, errmsg="日期输入有误")

    # 区域判断
    try:
        areas = Area.query.get(area_id)
    except Exception as e:
        return jsonify(errno=RET.PARAMERR, errmsg="区域信息有误")

    # 处理页数
    try:
        page = int(page)
    except Exception as e:
        page = 1

    # 查询数据库
    # 获取缓存数据 存储每个搜索组合, 增加内存开销
    redis_key = "house_%s_%s_%s_%s" % (start_date, end_date, area_id, sort_key)
    try:
        resp_json = redis_store.hget(redis_key, page)
    except Exception as e:
        resp_json = None
        logging.error("reids 获取缓存失败")
    else:
        if resp_json:
            return resp_json, 200, {"Content-Type": "application/json"}

    # 过滤条件的参数列表容器
    filter_params = list()

    # 形成参数: 填充过滤参数 时间条件
    conflict_orders = None
    try:
        if start_date and end_date:
            # 查询冲突的订单
            conflict_orders = Order.query.filter(
                Order.begin_date <= end_date,
                Order.end_date >= start_date).all()
        elif start_date:
            conflict_orders = Order.query.filter(
                Order.end_date >= start_date).all()
        elif end_date:
            conflict_orders = Order.query.filter(
                Order.begin_date <= end_date).all()

    except Exception as e:
        logging.error("Order数据库查询错误")
        return jsonify(errno=RET.DBERR, errmsg="数据库异常")

    if conflict_orders:
        # 从订单中获取冲突的房屋id
        conflict_house_ids = [order.house_id for order in conflict_orders]

        # 如果冲突的房屋id不为空,向查询参数中添加条件
        if conflict_house_ids:
            filter_params.append(House.id.notin_(conflict_house_ids))

    # 区域条件
    if area_id:
        # 放进去的是表达式: __eq__()方法的执行
        filter_params.append(House.area_id == area_id)

    # 查询数据库
    # 补充排序条件
    if sort_key == "booking":  # 入住做多
        house_query = House.query.filter(*filter_params).order_by(
            House.order_count.desc())
    elif sort_key == "price-inc":
        house_query = House.query.filter(*filter_params).order_by(
            House.price.asc())
    elif sort_key == "price-des":
        house_query = House.query.filter(*filter_params).order_by(
            House.price.desc())
    else:  # 新旧
        house_query = House.query.filter(*filter_params).order_by(
            House.create_time.desc())

    # 处理分页
    try:
        #                               当前页数          每页数据量                               自动的错误输出
        page_obj = house_query.paginate(
            page=page,
            per_page=constants.HOUSE_LIST_PAGE_CAPACITY,
            error_out=False)
    except Exception as e:
        logging.error("数据库查询错误")
        return jsonify(errno=RET.DBERR, errmsg="数据库异常")

    # 获取页面数据
    house_li = page_obj.items
    houses = []
    for house in house_li:
        houses.append(house.to_base_dict())

    # 获取总页数
    total_page = page_obj.pages

    resp_dict = dict(errno=RET.OK,
                     errmsg="OK",
                     data={
                         "total_page": total_page,
                         "houses": houses,
                         "current_page": page
                     })

    resp_json = json.dumps(resp_dict)

    if page <= total_page:
        # 设置缓存数据
        redis_key = "house_%s_%s_%s_%s" % (start_date, end_date, area_id,
                                           sort_key)
        # 哈希类型
        try:
            # redis_store.hset(redis_key, page, resp_json)
            # redis_store.expire(redis_key, constants.HOUES_LIST_PAGE_REDIS_CACHE_EXPIRES)

            # 创建redis管道对象,可以一次执行多个语句
            pipeline = redis_store.pipeline()

            # 开启多个语句的记录
            pipeline.multi()

            pipeline.hset(redis_key, page, resp_json)
            pipeline.expire(redis_key,
                            constants.HOUES_LIST_PAGE_REDIS_CACHE_EXPIRES)

            # 执行语句
            pipeline.execute()
        except Exception as e:
            logging.error("redis设置错误")

    return resp_json, 200, {"Content-Type": "application/json"}
Example #18
0
def send_houses_info():
    '''
    前端发送过来的json数据
    {
        "title":"",
        "price":"",
        "area_id":"1",
        "address":"",
        "room_count":"",
        "acreage":"",
        "unit":"",
        "capacity":"",
        "beds":"",
        "deposit":"",
        "min_days":"",
        "max_days":"",
        "facility":["7","8"]
    }
	'''
    logging = Use_Loggin()
    # 获取参数
    user_id = g.user_id
    house_dict = request.get_json()

    title = house_dict.get("title")
    price = house_dict.get("price")
    area_id = house_dict.get("area_id")
    address = house_dict.get("address")
    room_count = house_dict.get("room_count")
    acreage = house_dict.get("acreage")
    unit = house_dict.get("unit")  # 房屋布局
    capacity = house_dict.get("capacity")  # 房屋容纳数量
    beds = house_dict.get("beds")
    deposit = house_dict.get("deposit")  # 押金
    min_days = house_dict.get("min_days")
    max_days = house_dict.get("max_days")
    facility_ids = house_dict.get("facility")  # 设施可能是空

    # 校验参数, facility另外校验
    if not all([
            title, price, area_id, address, room_count, acreage, unit,
            capacity, beds, deposit, min_days, max_days
    ]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不完整")

    # 金额校验
    try:
        price = int(float(price) * 100)
        deposit = int(float(deposit) * 100)
    except Exception as e:
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    # 校验城区id是否存在
    try:
        area_sql_id = Area.query.get(area_id)
    except Exception as e:
        area_sql_id = None
    if area_sql_id is None:
        return jsonify(errno=RET.PARAMERR, errmsg="城区信息有误")

    # 其他--校验--略

    # 保存数据
    house = House(user_id=user_id,
                  area_id=area_id,
                  title=title,
                  price=price,
                  address=address,
                  room_count=room_count,
                  acreage=acreage,
                  unit=unit,
                  capacity=capacity,
                  beds=beds,
                  deposit=deposit,
                  min_days=min_days,
                  max_days=max_days)

    # 仅仅保存到session, 不报错
    db.session.add(house)

    # 处理房屋的设施信息,
    if facility_ids is not None:
        # ['7', '8']
        try:
            facility_obj = Facility.query.filter(
                Facility.id.in_(facility_ids)).all()
        except Exception as e:
            logging.error("设备信息数据库查询异常")
            return jsonify(errno=RET.DBERR, errmsg="数据库查询异常")

        if facility_obj:
            # 有合法的设施数据
            house.facilities = facility_obj

    try:
        db.session.add(house)
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        logging.error("数据库保存失败")
        return jsonify(errno=RET.DBERR, errmsg="房屋信息统一提交数据失败")

    return jsonify(errno=RET.OK, errmsg="保存数据成功", data={"house_id": house.id})