132 lines
5.3 KiB
Python
132 lines
5.3 KiB
Python
from flask import Blueprint, render_template, request, redirect, url_for, flash, session
|
|
from models import Movie, Genre, Rating, UserDefault, Occupation, User # 导入所需的模型
|
|
from sqlalchemy import func
|
|
from helpers import get_recommendations
|
|
|
|
# 创建一个蓝图
|
|
movies_bp = Blueprint('movies', __name__)
|
|
|
|
# 电影详情路由
|
|
@movies_bp.route('/detail')
|
|
def detail():
|
|
# 检查用户是否登录
|
|
if 'user_id' not in session:
|
|
flash("Please log in to access this page.")
|
|
return redirect(url_for('auth'))
|
|
|
|
# 获取电影 ID 参数
|
|
movie_id = request.args.get('id')
|
|
if not movie_id:
|
|
return redirect(url_for('dashboard'))
|
|
|
|
# 查询电影详情
|
|
movie = Movie.query.filter_by(id=movie_id).first()
|
|
if not movie:
|
|
return redirect(url_for('dashboard'))
|
|
|
|
# 解析 genres 字段,查询对应的 genre 名称
|
|
genre_ids = movie.genres.split(",") if movie.genres else []
|
|
genres = Genre.query.filter(Genre.id.in_(genre_ids)).all()
|
|
genre_names = [genre.name for genre in genres]
|
|
|
|
# 获取评分分布
|
|
rating_counts = (
|
|
Rating.query.with_entities(Rating.rating, func.count(Rating.rating).label('count'))
|
|
.filter_by(item_id=movie_id)
|
|
.group_by(Rating.rating)
|
|
.all()
|
|
)
|
|
total_ratings = sum(count for _, count in rating_counts)
|
|
rating_distribution = {i: 0 for i in range(1, 6)} # 初始化 1-5 分的评分比例为 0
|
|
for rating, count in rating_counts:
|
|
rating_distribution[rating] = count / total_ratings if total_ratings else 0
|
|
|
|
# 获取当前用户类型
|
|
user_id = session.get('user_id')
|
|
user = User.query.filter_by(id=user_id).first()
|
|
user_type = user.user_type if user else 'U' # 默认为普通用户
|
|
|
|
# 如果是制片人用户,进行用户喜好详细分析
|
|
user_analysis = None
|
|
if user_type == 'P':
|
|
# 性别分析
|
|
gender_stats = (
|
|
Rating.query.join(UserDefault, Rating.user_id == UserDefault.user_id)
|
|
.filter(Rating.item_id == movie_id)
|
|
.with_entities(UserDefault.gender, func.avg(Rating.rating).label('average'), func.count(Rating.rating).label('count'))
|
|
.group_by(UserDefault.gender)
|
|
.all()
|
|
)
|
|
gender_analysis = {gender: {'average': avg, 'count': cnt} for gender, avg, cnt in gender_stats}
|
|
|
|
# 年龄分析
|
|
age_ranges = [
|
|
(0, 10), (11, 20), (21, 30), (31, 40),
|
|
(41, 50), (51, 60), (61, 70), (71, 80)
|
|
]
|
|
age_analysis = {}
|
|
for min_age, max_age in age_ranges:
|
|
age_data = (
|
|
Rating.query.join(UserDefault, Rating.user_id == UserDefault.user_id)
|
|
.filter(Rating.item_id == movie_id, UserDefault.age.between(min_age, max_age))
|
|
.with_entities(func.avg(Rating.rating).label('average'), func.count(Rating.rating).label('count'))
|
|
.first()
|
|
)
|
|
age_analysis[f"{min_age}-{max_age}"] = {
|
|
'average': age_data.average if age_data and age_data.count else 0,
|
|
'count': age_data.count if age_data else 0
|
|
}
|
|
|
|
# 职业分析
|
|
occupation_stats = (
|
|
Rating.query.join(UserDefault, Rating.user_id == UserDefault.user_id)
|
|
.filter(Rating.item_id == movie_id)
|
|
.with_entities(UserDefault.occupation, func.avg(Rating.rating).label('average'), func.count(Rating.rating).label('count'))
|
|
.group_by(UserDefault.occupation)
|
|
.all()
|
|
)
|
|
occupation_analysis = {}
|
|
for occ_id, avg, cnt in occupation_stats:
|
|
occupation_name = Occupation.query.filter_by(id=occ_id).first().name
|
|
occupation_analysis[occupation_name] = {'average': avg, 'count': cnt}
|
|
|
|
user_analysis = {
|
|
'gender_analysis': gender_analysis,
|
|
'age_analysis': age_analysis,
|
|
'occupation_analysis': occupation_analysis
|
|
}
|
|
|
|
# 获取相似电影并转换每部相似电影的 genres 为名称
|
|
similar_movie_ids = [int(mid) for mid in movie.similar_movie.split(',')] if movie.similar_movie else []
|
|
similar_movies = Movie.query.filter(Movie.id.in_(similar_movie_ids)).all()
|
|
similar_movies_data = []
|
|
for sim_movie in similar_movies:
|
|
sim_genre_ids = sim_movie.genres.split(",") if sim_movie.genres else []
|
|
sim_genres = Genre.query.filter(Genre.id.in_(sim_genre_ids)).all()
|
|
sim_genre_names = [genre.name for genre in sim_genres]
|
|
|
|
similar_movies_data.append({
|
|
'id': sim_movie.id,
|
|
'title': sim_movie.title,
|
|
'release_date': sim_movie.release_date,
|
|
'genres': ", ".join(sim_genre_names), # 转换后的 genres 名称
|
|
'rating_count': sim_movie.rating_count,
|
|
'average_rating': sim_movie.average_rating,
|
|
'actor': sim_movie.actor,
|
|
})
|
|
|
|
# 获取“猜你喜欢”的推荐数据
|
|
recommendations_data = get_recommendations(user_id, page=1, per_page=10) if user_id else {}
|
|
|
|
# 渲染电影详情模板
|
|
return render_template(
|
|
'detail.html',
|
|
movie=movie,
|
|
genre_names=genre_names,
|
|
rating_distribution=rating_distribution,
|
|
user_analysis=user_analysis,
|
|
user_type=user_type,
|
|
**recommendations_data,
|
|
similar_movies=similar_movies_data, # 使用转换后的相似电影数据
|
|
)
|