blob: 11c0b9e9339b97aace9995e65b529fd1602d4622 [file] [log] [blame]
wueb6e6ca2025-06-15 10:35:32 +08001# routes/posts.py
wu90da17b2025-06-19 12:45:29 +08002
wueb6e6ca2025-06-15 10:35:32 +08003from flask import Blueprint, request, jsonify, abort
4from extensions import db
5from models.post import Post
6from models.behavior import Behavior
7
8posts_bp = Blueprint('posts', __name__)
9
10@posts_bp.route('', methods=['POST'])
11def create_post():
12 data = request.get_json() or {}
13 post = Post(**data)
14 db.session.add(post)
15 db.session.commit()
16 return jsonify({'id': post.id}), 201
17
18@posts_bp.route('', methods=['GET'])
19def list_posts():
wu90da17b2025-06-19 12:45:29 +080020 """
21 获取帖子列表,支持:
22 - GET /posts 返回所有已发布帖子
23 - GET /posts?user_id=123 返回指定用户 user_id 的所有帖子
24 """
25 user_id = request.args.get('user_id', type=int)
26 query = Post.query
27 if user_id is not None:
28 query = query.filter_by(user_id=user_id)
29 else:
30 query = query.filter_by(status='published')
31 posts = query.all()
32
wueb6e6ca2025-06-15 10:35:32 +080033 return jsonify([{
34 'id': p.id,
35 'title': p.title,
36 'heat': p.heat,
wu90da17b2025-06-19 12:45:29 +080037 'status': p.status,
wueb6e6ca2025-06-15 10:35:32 +080038 'created_at': p.created_at.isoformat()
39 } for p in posts])
40
41@posts_bp.route('/<int:post_id>', methods=['GET'])
42def get_post(post_id):
43 post = Post.query.get_or_404(post_id)
44 return jsonify({
45 'id': post.id,
46 'user_id': post.user_id,
wu90da17b2025-06-19 12:45:29 +080047 'topic_id': post.topic_id,
wueb6e6ca2025-06-15 10:35:32 +080048 'title': post.title,
49 'content': post.content,
50 'media_urls': post.media_urls,
51 'status': post.status,
52 'heat': post.heat,
53 'created_at': post.created_at.isoformat(),
54 'updated_at': post.updated_at.isoformat()
55 })
56
57@posts_bp.route('/<int:post_id>', methods=['PUT'])
58def update_post(post_id):
59 """
wu90da17b2025-06-19 12:45:29 +080060 修改帖子字段(可选字段:title, content, topic_id, media_urls, status)
wueb6e6ca2025-06-15 10:35:32 +080061 """
62 post = Post.query.get_or_404(post_id)
63 data = request.get_json() or {}
wu90da17b2025-06-19 12:45:29 +080064 for key in ('title', 'content', 'topic_id', 'media_urls', 'status'):
wueb6e6ca2025-06-15 10:35:32 +080065 if key in data:
66 setattr(post, key, data[key])
67 db.session.commit()
68 return '', 204
69
70@posts_bp.route('/<int:post_id>', methods=['DELETE'])
71def delete_post(post_id):
72 post = Post.query.get_or_404(post_id)
73 db.session.delete(post)
74 db.session.commit()
75 return '', 204
76
wueb6e6ca2025-06-15 10:35:32 +080077@posts_bp.route('/<int:post_id>/<action>', methods=['POST'])
78def post_action(post_id, action):
79 """
80 支持的 action: like, favorite, view, share
81 对于 like 和 favorite,保证每个用户每帖只做一次。
82 """
83 if action not in ('like', 'favorite', 'view', 'share'):
84 abort(400, 'Invalid action')
85
86 data = request.get_json() or {}
87 user_id = data.get('user_id')
88 if not user_id:
89 abort(400, 'user_id required')
90
91 # 对 like/favorite 做去重检查
92 if action in ('like', 'favorite'):
93 exists = Behavior.query.filter_by(
94 user_id=user_id,
95 post_id=post_id,
96 type=action
97 ).first()
98 if exists:
99 return jsonify({'error': f'already {action}d'}), 400
100
101 # 创建行为记录
102 beh = Behavior(user_id=user_id, post_id=post_id, type=action)
103 db.session.add(beh)
104
105 # 更新热度
106 post = Post.query.get_or_404(post_id)
107 post.heat += 1
108
109 db.session.commit()
110 return '', 201
111
wueb6e6ca2025-06-15 10:35:32 +0800112@posts_bp.route('/<int:post_id>/like', methods=['DELETE'])
113def unlike(post_id):
114 user_id = request.get_json(silent=True) and request.get_json().get('user_id')
115 if not user_id:
116 abort(400, 'user_id required')
117 # 查找已有的 like 行为
118 beh = Behavior.query.filter_by(
119 user_id=user_id,
120 post_id=post_id,
121 type='like'
122 ).first()
123 if not beh:
124 return jsonify({'error': 'not liked yet'}), 400
125
126 db.session.delete(beh)
127 # 更新热度,确保不降到负数
128 post = Post.query.get_or_404(post_id)
129 post.heat = max(post.heat - 1, 0)
130 db.session.commit()
131 return '', 204
132
wueb6e6ca2025-06-15 10:35:32 +0800133@posts_bp.route('/<int:post_id>/favorite', methods=['DELETE'])
134def unfavorite(post_id):
135 user_id = request.get_json(silent=True) and request.get_json().get('user_id')
136 if not user_id:
137 abort(400, 'user_id required')
138 # 查找已有的 favorite 行为
139 beh = Behavior.query.filter_by(
140 user_id=user_id,
141 post_id=post_id,
142 type='favorite'
143 ).first()
144 if not beh:
145 return jsonify({'error': 'not favorited yet'}), 400
146
147 db.session.delete(beh)
148 # 更新热度
149 post = Post.query.get_or_404(post_id)
150 post.heat = max(post.heat - 1, 0)
151 db.session.commit()
152 return '', 204