blob: 11c0b9e9339b97aace9995e65b529fd1602d4622 [file] [log] [blame]
# routes/posts.py
from flask import Blueprint, request, jsonify, abort
from extensions import db
from models.post import Post
from models.behavior import Behavior
posts_bp = Blueprint('posts', __name__)
@posts_bp.route('', methods=['POST'])
def create_post():
data = request.get_json() or {}
post = Post(**data)
db.session.add(post)
db.session.commit()
return jsonify({'id': post.id}), 201
@posts_bp.route('', methods=['GET'])
def list_posts():
"""
获取帖子列表,支持:
- GET /posts 返回所有已发布帖子
- GET /posts?user_id=123 返回指定用户 user_id 的所有帖子
"""
user_id = request.args.get('user_id', type=int)
query = Post.query
if user_id is not None:
query = query.filter_by(user_id=user_id)
else:
query = query.filter_by(status='published')
posts = query.all()
return jsonify([{
'id': p.id,
'title': p.title,
'heat': p.heat,
'status': p.status,
'created_at': p.created_at.isoformat()
} for p in posts])
@posts_bp.route('/<int:post_id>', methods=['GET'])
def get_post(post_id):
post = Post.query.get_or_404(post_id)
return jsonify({
'id': post.id,
'user_id': post.user_id,
'topic_id': post.topic_id,
'title': post.title,
'content': post.content,
'media_urls': post.media_urls,
'status': post.status,
'heat': post.heat,
'created_at': post.created_at.isoformat(),
'updated_at': post.updated_at.isoformat()
})
@posts_bp.route('/<int:post_id>', methods=['PUT'])
def update_post(post_id):
"""
修改帖子字段(可选字段:title, content, topic_id, media_urls, status)
"""
post = Post.query.get_or_404(post_id)
data = request.get_json() or {}
for key in ('title', 'content', 'topic_id', 'media_urls', 'status'):
if key in data:
setattr(post, key, data[key])
db.session.commit()
return '', 204
@posts_bp.route('/<int:post_id>', methods=['DELETE'])
def delete_post(post_id):
post = Post.query.get_or_404(post_id)
db.session.delete(post)
db.session.commit()
return '', 204
@posts_bp.route('/<int:post_id>/<action>', methods=['POST'])
def post_action(post_id, action):
"""
支持的 action: like, favorite, view, share
对于 like 和 favorite,保证每个用户每帖只做一次。
"""
if action not in ('like', 'favorite', 'view', 'share'):
abort(400, 'Invalid action')
data = request.get_json() or {}
user_id = data.get('user_id')
if not user_id:
abort(400, 'user_id required')
# 对 like/favorite 做去重检查
if action in ('like', 'favorite'):
exists = Behavior.query.filter_by(
user_id=user_id,
post_id=post_id,
type=action
).first()
if exists:
return jsonify({'error': f'already {action}d'}), 400
# 创建行为记录
beh = Behavior(user_id=user_id, post_id=post_id, type=action)
db.session.add(beh)
# 更新热度
post = Post.query.get_or_404(post_id)
post.heat += 1
db.session.commit()
return '', 201
@posts_bp.route('/<int:post_id>/like', methods=['DELETE'])
def unlike(post_id):
user_id = request.get_json(silent=True) and request.get_json().get('user_id')
if not user_id:
abort(400, 'user_id required')
# 查找已有的 like 行为
beh = Behavior.query.filter_by(
user_id=user_id,
post_id=post_id,
type='like'
).first()
if not beh:
return jsonify({'error': 'not liked yet'}), 400
db.session.delete(beh)
# 更新热度,确保不降到负数
post = Post.query.get_or_404(post_id)
post.heat = max(post.heat - 1, 0)
db.session.commit()
return '', 204
@posts_bp.route('/<int:post_id>/favorite', methods=['DELETE'])
def unfavorite(post_id):
user_id = request.get_json(silent=True) and request.get_json().get('user_id')
if not user_id:
abort(400, 'user_id required')
# 查找已有的 favorite 行为
beh = Behavior.query.filter_by(
user_id=user_id,
post_id=post_id,
type='favorite'
).first()
if not beh:
return jsonify({'error': 'not favorited yet'}), 400
db.session.delete(beh)
# 更新热度
post = Post.query.get_or_404(post_id)
post.heat = max(post.heat - 1, 0)
db.session.commit()
return '', 204