이번에 구현할 엔드포인트는 팔로우와 언팔로우 기능이다. 팔로우 한 사용자의 타임라인을 볼 수 있게 하는 기능이다. 팔로우, 언팔로우하고 싶은 사용자의 아이디를 HTTP 요청으로 보내면 API에서 요청을 처리하는 식으로 구현할 것이다.
팔로우 엔드포이트에 전송할 JSON 데이터는 다음과 같다.
{"id" : 1, "follow" : 2} # id는 해당 사용자의 아이디, follow는 팔로우 하고자하는 사용자의 아이디
언팔로우 엔드포인트에 전송할 JSON 데이터는 다음과 같다.
{"id" : 1, "unfollow" : 2}
팔로우와 언팔로우의 코드는 다음과 같다.
@app.route("/follow", methods=['POST'])
def follow():
payload = request.json
user_id = int(payload['id'])
user_id_to_follow = int(payload['follow']) # 언팔로우는 unfollow 입력
if user_id not in app.users or user_id_to_follow not in app.users:
return '사용자가 존재하지 않습니다.', 400
user = app.users[user_id]
user.setdefault('follow', set()).add(user_id_to_follow) # unfollow 의 경우 add 대신에 discard
return jsonify(user)
팔로우, 언팔로우 요청이 중복되게 들어온 경우 중복된 ID가 여러번 저장되는 것을 방지하기 위해서 list가 아닌 set을 사용한다.
문제는 set은 list 와 다르게 json 모듈에 의해 JSON으로 변경되지 않는다. 따라서 임의로 set을 json으로 변환하도록 해야 하는데 이를 위해서 기존의 JSONEncoder를 상속하는 CustomJSONEncoder 클래스를 만들어 해결하도록 한다. 코드는 아래와 같다.
from flask.json import JSONEncoder
class CustomJSONEncoder(JSONEncoder):
def default(self, obj):
if isinstance(obj, set):
return list(obj)
return JSONEncoder.default(self, obj)
app.json_encoder = CustomJSONEncoder
지금까지의 전체 코드는 다음과 같다.
from flask import Flask, jsonify, request
from flask.json import JSONEncoder
class CustomJSONEncoder(JSONEncoder):
def default(self, obj):
if isinstance(obj, set):
return list(obj)
return JSONEncoder.default(self, obj)
app = Flask(__name__)
app.id_count = 1
app.users = {}
app.tweets = []
app.json_encoder = CustomJSONEncoder
@app.route("/ping", methods=['GET'])
def ping():
return "pong"
@app.route("/sign-up", methods=['POST'])
def sign_up():
new_user = request.json
new_user["id"] = app.id_count
app.users[app.id_count] = new_user
app.id_count = app.id_count +1
return jsonify(new_user)
@app.route("/tweet", methods=['POST'])
def tweet():
payload = request.json
user_id = int(payload['id'])
tweet = payload['tweet']
if user_id not in app.users:
return '사용자가 존재하지 않습니다.', 400
if len(tweet) > 300:
return '300자를 초과했습니다.', 400
user_id = int(payload['id'])
app.tweets.append({'user_id': user_id, 'tweet': tweet})
return '', 200
@app.route("/follow", methods=['POST'])
def follow():
payload = request.json
user_id = int(payload['id'])
user_id_to_follow = int(payload['follow'])
if user_id not in app.users or user_id_to_follow not in app.users:
return '사용자가 존재하지 않습니다.', 400
user = app.users[user_id]
user.setdefault('follow', set()).add(user_id_to_follow)
return jsonify(user)
@app.route("/unfollow", methods=['POST'])
def unfollow():
payload = request.json
user_id = int(payload['id'])
user_id_to_follow = int(payload['unfollow'])
if user_id not in app.users or user_id_to_follow not in app.users:
return '사용자가 존재하지 않습니다.', 400
user = app.users[user_id]
user.setdefault('follow', set()).discard(user_id_to_follow)
return jsonify(user)