def post(valid_class, parse, template): """ 一些固定的对象的方法模板 多用于post和put :param valid_class: :param parse: :param template: :return: """ if isinstance(parse, dict): valid = valid_class(parse) elif isinstance(parse, reqparse.RequestParser): valid = valid_class(parse.parse_args()) else: raise ValueError("parse must be dict or RequestParser") err_map = valid.valid_data() if err_map: response = Response() response.data = err_map response.errno = len(err_map) response.code = FORMAT_ERROR return response clean_data = valid.clean_data # for key in template.__dict__: # if template.__dict__[key] is None: # setattr(template, key, clean_data[key]) for key in clean_data: if not key.startswith("_"): setattr(template, key, clean_data[key])
def put(self): """ 修改课程的接口 :return: """ response = Response() try: _id = request.json["id"] course = CourseTemplate() response = post(CourseValid, parse, course) if response: return jsonify(response.dict_data) ret = execute_sql(UpdateMap.update_course_by_id, [ course.name, course.type, course.level, course.burning, course.id ]) if ret == 0: raise UserDoesNotExistException("课程不存在") response.data = { "id": course.id, "name": course.name, "type": course.type, "level": course.level, "burning": course.burning } except KeyError as e: init_key_error_handler(response, e, "缺少入参:") except UserDoesNotExistException as e: init_key_error_handler(response, e) return jsonify(response.dict_data)
def get(self): """ 获取一个特定的挑战的接口 根据course id 请求需要携带一个参数 id 由于挑战 不用登陆也可以访问 所以不加权,此pageviews每请求一次就会增加一次 在多线程环境下会不准确 但是没关系 问题不大 :return: """ response = Response() try: _id = request.args["id"] challenge = fetchone_dict(SelectMap.challenge_by_id, [_id, ], ChallengeTemplate) if challenge: ret = execute_sql(UpdateMap.update_challenge_pageviews, [challenge.id, ]) if ret == 0: raise InvalidArgumentException("数据不存在") response.data = { "id": challenge.id, "picture": challenge.picture, "content": challenge.content, "start_time": challenge.start_time, "end_time": challenge.end_time, "create_time": challenge.create_time, "pageviews": challenge.pageviews + 1 } return jsonify(response.dict_data) raise InvalidArgumentException("数据不存在") except Exception as e: init_key_error_handler(response, e, "信息:") return jsonify(response.dict_data)
def post(self): comment = CommentTemplate() response = post(CommentValid, parse, comment) if response: return jsonify(response.dict_data) try: response = Response() now = datetime.datetime.now() user_id = getattr(request, "user")["id"] user = fetchone_dict(SelectMap.user_info_by_user_id, (user_id, ), GeneralObject) ret = execute_sql(InsertMap.comment, (comment.content, now, comment.blog_id, user_id, user.nick_name), True) if ret == 0: raise InvalidArgumentException("评论失败") response.data = { "id": ret, "create_time": now, "content": comment.content, "blog_id": comment.blog_id, "user_id": user_id, "nick_name": user.nick_name } except Exception as e: init_key_error_handler(response, e, "信息:") return jsonify(response.dict_data)
def post(self): """ 添加挑战的接口 此接口的content是一个重点 是有格式要求的 要求就是 其中的html不能包含script标签 也不能含有任何的注释 添加挑战的另一个约定就是 start_time和end_time是有格式要求的 必须是2019-11-03这种格式 无法配置 :return: """ challenge = ChallengeTemplate() response = post(ChallengeValid, parse, challenge) if response is None: response = Response() try: number = generate_number(20) ret = execute_sql(InsertMap.challenge, [ challenge.picture, challenge.content, challenge.start_time, challenge.end_time, datetime.datetime.now(), challenge.pageviews, number ]) if ret == 0: raise InvalidArgumentException("数据写入失败") challenge = fetchone_dict(SelectMap.challenge_by_number, [number, ], ChallengeTemplate) response.data = { "id": challenge.id, "picture": challenge.picture, "content": challenge.content, "start_time": challenge.start_time, "end_time": challenge.end_time, "create_time": challenge.create_time, "pageviews": challenge.pageviews } except Exception as e: init_key_error_handler(response, e, "信息:") return jsonify(response.dict_data)
def get(self): args = request.args course_id = args.get("id", 0) response = Response() offset = request.args.get("offset", current_app.config["PAGE_OFFSET"]) offset = int(offset) default_url = os.path.join(current_app.config["MEDIA_URL"], "default_course.jpg") try: user_id = getattr(request, "user", {}).get("id") ret_list = fetchall_dict(SelectMap.course_list_by_page, (course_id, offset), GeneralObject) ret_json = [] if user_id: for course in ret_list: collect = fetchone_dict(SelectMap.collect_by_course_id, (course.id, user_id), GeneralObject) course.is_collect = True if collect else False course.collect_id = collect.id if collect else None action = fetchone_dict(SelectMap.action_list_by_course_id, (course.id,), GeneralObject) course.picture = action.picture if action else default_url ret_json.append(course.data) else: for course in ret_list: course.is_collect = False course.collect_id = None ret_json.append(course.data) response.data = { "course_list": ret_json, "count": len(ret_json), "query_id": ret_list[-1].id, "last_query_id": course_id, "page_offset": offset } return jsonify(response.dict_data) except Exception as e: init_key_error_handler(response, e, "错误:") return jsonify(response.dict_data)
def post(self): """ 添加帖子的接口 帖子的添加需要携带 user_id content title picture 等键值对 图片需要先上传 content需要不存在注释以及script标签 :return: """ response = Response() blog = BlogTemplate() resp = post(BlogValid, parser, blog) if resp is not None: return resp try: from datetime import datetime now = datetime.now() row_id = execute_sql( InsertMap.blog, (blog.user_id, blog.content, blog.title, blog.picture, now)) if row_id == 0: raise InvalidArgumentException("插入记录失败") response.data = { "id": row_id, "user_id": blog.user_id, "content": blog.content, "title": blog.title, "picture": blog.picture, "create_time": now } except Exception as e: init_key_error_handler(response, e, "信息:") return jsonify(response.dict_data)
def inner(*args, **kwargs): response = Response() user_permission = getattr(g, "user", {}).get("permission", 0) if permission & user_permission == permission: return func(*args, **kwargs) else: response.code = PERMISSION_ERROR response.errno = 1 response.data = {"msg": "权限不足"} return jsonify(response.dict_data)
def inner(*args, **kwargs): response = Response() ip = request.remote_addr if ip not in ip_map: ip_map[ip] = _IpStack(times, seconds) ret = ip_map[ip].append(time.time()) if ret: return func(*args, **kwargs) else: response.errno = 1 response.code = THROTTLE_ERROR response.data = {"msg": "请求过于频繁,稍后再试"} return jsonify(response.dict_data)
def delete(self): """ 删除课程接口 但是并不会删除action :return: """ response = Response() try: _id = request.json["id"] course_num = execute_sql(DeleteMap.course_by_id, [_id, ]) response.data = {"msg": "ok", "count": course_num} except KeyError as e: init_key_error_handler(response, e) return jsonify(response.dict_data)
def delete(self): upper = UpperTemplate() response = post(UpperValid, parse, upper) if response: return jsonify(response) try: user_id = getattr(request, "user")["id"] response = Response() ret = execute_sql(DeleteMap.upper_by_id, (upper.blog_id, user_id)) if ret == 0: raise InvalidArgumentException("取消失败") execute_sql(UpdateMap.blog_upper_dev, (upper.blog_id, )) response.data = {"msg": "ok"} except Exception as e: init_key_error_handler(response, e, "信息:") return jsonify(response.dict_data)
def delete(self): response = Response() try: _id = request.json["id"] comment_count = execute_sql(DeleteMap.comment_by_id, (_id, )) if comment_count == 0: raise InvalidArgumentException("删除失败!") reply_count = execute_sql(DeleteMap.reply_by_comment_id, (_id, )) response.data = { "comment_count": comment_count, "reply_count": reply_count, "msg": "ok" } except Exception as e: init_key_error_handler(response, e, "信息:") return jsonify(response.dict_data)
def inner(*args, **kwargs): response = Response() content = f"{request.url}:{request.remote_addr}" md5 = hashlib.md5(current_app.config["SALT"].encode( current_app.config["DB_CHARSET"])) md5.update(content.encode(current_app.config["DB_CHARSET"])) val = md5.hexdigest() if val in content_set: response.code = THROTTLE_ERROR response.errno = 1 response.data = {"msg": "请求正在处理中"} return jsonify(response.dict_data) content_set.add(val) ret = func(*args, **kwargs) content_set.remove(val) return ret
def delete(self): response = Response() try: _id = request.json["id"] b = fetchone_dict(SelectMap.blog_by_id, (_id, ), GeneralObject) permission = getattr(request, "user")["permission"] if getattr( request, "user")["id"] != b.user_id and permission & ADMIN != ADMIN: raise InvalidArgumentException("权限不足") ret = execute_sql(DeleteMap.blog_by_id, (_id, )) if ret == 0: raise InvalidArgumentException("删除失败") response.data = {"msg": "ok"} except Exception as e: init_key_error_handler(response, e, "信息:") return jsonify(response.dict_data)
def delete(self): response = Response() try: _id = request.json["id"] ret = execute_sql(DeleteMap.challenge_by_id, (_id, )) if ret == 0: raise UserDoesNotExistException("挑战不存在") except Exception as e: init_key_error_handler(response, e, "信息") return jsonify(response.dict_data)
def put(self): """ 修改,修改用户信息使用此方法 tag代表了你想要的动作 有3个选项 all 全部的 avatar 头像 description 描述信息 当你传all 的时候 需要同时传所有的信息 包括未被修改的部分 :return: """ response = Response() connection = pool.connection() try: tag = request.json.get("tag", "all") user_id = request.json.get("id") or getattr(g, "user")["id"] getattr(self, "_update_" + tag)(connection, user_id) response.data = {"msg": "ok"} except (KeyError, AttributeError, InvalidArgumentException) as e: init_key_error_handler(response, e) finally: connection.close() return jsonify(response.dict_data)
def get(self): response = Response() try: tag = request.args.get("tag", "back") func = getattr(self, f"_{tag}_list") func(response) except Exception as e: init_key_error_handler(response, e, "信息:") import traceback traceback.print_exc() return jsonify(response.dict_data)
def post(self): """ 文件上传的接口,可以上传多个文件 :return: """ files = request.files.getlist(current_app.config["UPLOAD_FILE_KEY"]) response = Response() media_url = current_app.config["MEDIA_URL"] media_dir = current_app.config["MEDIA_DIR"] err_list = [] suffix_list = [] for f in files: if is_safe(f.filename): suffix_list.append(get_suffix(f.filename)) continue err_list.append(f.filename) if err_list: response.errno = len(err_list) response.code = FORMAT_ERROR response.data = {"msg": "错误的文件类型:" + ",".join(err_list)} return jsonify(response.dict_data) file_url = [] for index, f in enumerate(files): file_name = generate_filename() + "." + suffix_list[index] path = os.path.join(media_dir, file_name) file_name = self._save(f, path, file_name) file_url.append({ "url": os.path.join(media_url, file_name), "filename": file_name }) response.data = {"msg": file_url} return jsonify(response.dict_data)
def _delete_user(self, user_id, connection): """ 删除一个用户的具体逻辑,包括判断用户是否存在等,此方法如果用户不存在会 抛出异常 :param user_id: 想要删除的用户的id :param connection: 数据库连接的conn对象 :return: 抛出异常或者返回response对象 """ cursor = connection.cursor() user = get_one(cursor, SelectMap.user_valid_by_id, user_id) response = Response() if user: try: ret1 = delete_sql_execute(cursor, DeleteMap.user_by_id, user_id) ret2 = delete_sql_execute(cursor, DeleteMap.user_info_by_user_id, user_id) connection.commit() response.data = {"msg": ret1 + ret2} except Exception as e: connection.rollback() connection.commit() response.code = 500 response.errno = 1 response.data = {"msg": "内部错误:" + str(e)} finally: cursor.close() connection.close() return response raise UserDoesNotExistException("用户不存在")
def post(self): """ 此方法用来添加一个对应课程的动作 但是此方法不会校验sequence(动作编号),所以请谨慎调用 :return: """ template = ActionTemplate() ret = post(ActionValid, parse, template) response = Response() if ret: return jsonify(ret.dict_data) try: count = execute_sql(InsertMap.action, [ template.id, template.content, template.picture, template.sequence ]) response.data = { "course_id": template.id, "content": template.content, "picture": template.picture, "sequence": template.sequence, "count": count } except Exception as e: init_key_error_handler(response, e) return jsonify(response.dict_data)
def delete(self): response = Response() try: user_id = request.json["id"] connection = pool.connection() response = self._delete_user(user_id, connection) except UserDoesNotExistException as e: response.code = 405 response.errno = 1 response.data = {"msg": str(e)} except KeyError: response.code = 405 response.errno = 1 response.data = {"msg": "你必须传一个id"} return jsonify(response.dict_data)
def get(self): response = Response() try: _id = request.args["id"] blog = fetchone_dict(SelectMap.blog_by_id, (_id, ), BlogTemplate) if blog is None: raise InvalidArgumentException("数据不存在") user = fetchone_dict(SelectMap.user_info_by_user_id, (blog.user_id, ), GeneralObject) response.data = blog.__dict__ response.data.update({ "nick_name": user.nick_name, "gender": user.gender, "email": user.email, "avatar": user.avatar, "permission": user.permission }) req = fetchone_dict(SelectMap.comment_and_reply_count_by_blog, (_id, ), GeneralObject) response.data.update({"comment_count": req.count}) except Exception as e: init_key_error_handler(response, e, "信息:") return jsonify(response.dict_data)
def put(self): """ 修改挑战的接口 和post接口相比 需要多传一个id的key 如果id不存在 则无法执行 :return: """ challenge = ChallengeTemplate() response = post(ChallengeValid, parse, template=challenge) if response is None: response = Response() try: _id = challenge.id ret = execute_sql(UpdateMap.update_challenge_by_id, [ challenge.picture, challenge.content, challenge.start_time, challenge.end_time, _id ]) if ret == 0: raise InvalidArgumentException("数据不存在") except InvalidArgumentException as e: response.errno = 1 response.code = 403 response.data = {"msg": str(e)} except Exception as e: init_key_error_handler(response, e, "信息:") return jsonify(response.dict_data)
def get(self): """ 带分页的 get方法获取所有的用户 用于在后台管理显示 缺点为,我不会关心你这个id的合法性,假如每页要显示的数量为10个 但是 你给了我一个10个中的1个id 对于这种情况我不会进行校验 此方法不会包含你传过来的id对应的用户,只会传过来以你传过来的id为头但是不含此id的LIMIT个用户,并将此结果集的最后一个用户的id单独返回 用来作为下次请求的参数,如果你是首次请求,则默认选择的起始id为0 :return: """ response = Response() try: tag = request.args.get("tag", "back") func = getattr(self, f"_{tag}_list") func(response) except (KeyError, UserDoesNotExistException) as e: init_key_error_handler(response, e) return jsonify(response.dict_data)
def inner(*args, **kwargs): response = Response() key = current_app.config["AUTH_CODE_SESSION_KEY"] try: auth_code = session[key].lower() code = request.args.get(key).lower() if code != auth_code: raise InvalidArgumentException() ret = func(*args, **kwargs) session.clear() return ret except (KeyError, AttributeError): response.code = FORMAT_ERROR response.errno = 1 response.data = {"msg": "验证码已失效 重新输入"} except InvalidArgumentException: response.code = FORMAT_ERROR response.errno = 1 response.data = {"msg": "验证码校验错误"} return jsonify(response.dict_data)
def _rollback(self, upper): response = Response() user_id = getattr(request, "user")["id"] ret = execute_sql(UpdateMap.update_upper_by_user_and_blog, (upper.blog_id, user_id)) if ret == 0: response.code = FORMAT_ERROR response.errno = 1 response.data = {"msg": "点赞失败"} return response response.data = { "user_id": upper.user_id, "blog_id": upper.blog_id, "create_time": upper.create_time } return response
def _real_insert(self, upper): response = Response() now = datetime.datetime.now() user_id = getattr(request, "user")["id"] ret = execute_sql(InsertMap.upper, (upper.blog_id, user_id, now), True) if ret == 0: response.code = FORMAT_ERROR response.errno = 1 response.data = {"msg": "点赞失败"} return response response.data = { "id": ret, "user_id": upper.user_id, "blog_id": upper.blog_id, "create_time": now } return response
def get(self): """ get方法的接口,获取单个的用户,通过账号密码,如果用户存在,则返回用户信息和token :return: """ account = request.args["account"] password = md5(request.args["password"]) response = Response() connection = pool.connection() cursor = connection.cursor() try: if account == "" or password == "": raise InvalidArgumentException("账号或密码不可为空") ret = get_one(cursor, SelectMap.user_info_with_login, [account, password]) if ret is None: raise UserDoesNotExistException("错误的用户名或密码") response.data = { "id": ret[0], "account": ret[1], "permission": ret[2], "phone": ret[3], "email": ret[4], "gender": ret[5], "avatar": ret[6], "description": ret[7], "nick_name": ret[10], "create_time": ret[9], "age": ret[11], "token": self._make_jwt(ret) } except UserDoesNotExistException as e: init_key_error_handler(response, e, "提示:") except Exception as e: response.code = 500 response.errno = 1 response.data = {"msg": "获取用户失败:" + str(e)} finally: cursor.close() connection.close() return jsonify(response.dict_data)
def post(self): valid = CourseValid(parse.parse_args()) err_map = valid.valid_data() response = Response() if err_map: response.data = err_map response.errno = len(err_map) response.code = FORMAT_ERROR return jsonify(response.dict_data) try: data = valid.clean_data execute_sql(InsertMap.course, [ data["type"], data["name"], datetime.datetime.now(), data["level"], data["burning"] ]) ret = execute_query_sql(SelectMap.course_by_create, [data["name"], ], lambda c: c.fetchone()) response.data = { "id": ret[0], "type": ret[1], "name": ret[2], "create_time": ret[3], "level": ret[4], "burning": ret[5] } except Exception as e: init_key_error_handler(response, e, "插入数据失败:") return jsonify(response.dict_data)
def jwt_handler(): """ json web token的处理函数,如果携带了token 则处理 否则略 :return: """ if request.is_json: token = request.json.get("token") elif request.method != "GET": token = request.form.get("token") else: token = request.args.get("token") if token is not None: response = Response() try: header, payload, signature = token.split(".") header = decode_base64(header) payload = decode_base64(payload) payload_handler(payload) alg = header_handler(header) signature_handler(header, payload, signature, alg) except TokenTimeOutException as e: response.code = PERMISSION_ERROR response.errno = 1 response.data = {"msg": str(e)} except (KeyError, IndexError, IllegalTokenException) as e: response.code = FORMAT_ERROR response.errno = 1 response.data = {"msg": "错误的token:" + str(e)} except ValueError: response.code = FORMAT_ERROR response.errno = 1 response.data = {"msg": "token格式错误"} except Exception as e: response.code = SERVER_ERROR response.errno = 1 response.data = {"msg": "服务端错误:" + str(e)} finally: if response.errno > 0: if hasattr(request, "user"): delattr(request, "user") return jsonify(response.dict_data)