You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask/Jinja实现单张狗狗图片评分后切换的方法求助

实现Hot or Not式单张图片切换方案

给你两个简单可行的实现方案,优先选第一个,改动最小、见效最快:


方案一:纯前端JavaScript控制(无需大量修改后端)

这个方案直接把所有图片加载到页面,用JS控制只显示当前张,评分后切换到下一张,适合快速上线。

1. 优化后端数据处理(避免前端冗余replace)

先修改app.py的arena函数,把数据库返回的元组列表转换成纯图片路径的列表,这样前端不用一堆replace:

@app.route("/arena", methods=["GET", "POST"])
@login_required
def arena():
    if request.method == "GET":
        try:
            conn = sqlite3.connect('dogs.db')
            cursor = conn.cursor()
            sql = "SELECT photo_address FROM photos;"
            cursor.execute(sql)
            rows = cursor.fetchall()
            # 把元组列表转成纯字符串列表
            photos = [row[0] for row in rows]
            
        except sqlite3.Error as er:
            conn.rollback()
            print('SQLite error: %s' % (' '.join(er.args)))
            flash("Oops, There was an gathering error!")
            return render_template("arena.html")

        else:
            conn.close()
            return render_template("arena.html", photos=photos)

2. 修改前端页面(arena.html)

添加CSS控制显示隐藏,加评分按钮,用JS实现切换逻辑:

{% extends "layout.html" %}

{% block title %}
    Arena
{% endblock %}

{% block head %}
<style>
/* 默认隐藏所有图片,只显示激活的那张 */
.dog-photo {
    display: none;
    margin: 0 auto;
    max-width: 80%;
    max-height: 60vh;
}
.dog-photo.active {
    display: block;
}
.rating-buttons {
    margin-top: 20px;
    text-align: center;
}
.rating-buttons button {
    padding: 10px 24px;
    font-size: 18px;
    margin: 0 12px;
    cursor: pointer;
    border: none;
    border-radius: 8px;
}
#btn-like {
    background-color: #4CAF50;
    color: white;
}
#btn-dislike {
    background-color: #f44336;
    color: white;
}
</style>
{% endblock %}

{% block main %}
<div class="photo-wrapper">
    {% for photo in photos %}
    <div class="dog-photo {% if loop.first %}active{% endif %}">
        <img src="{{ photo }}" alt="狗狗照片">
    </div>
    {% endfor %}
</div>

<div class="rating-buttons">
    <button id="btn-dislike">👎 不喜欢</button>
    <button id="btn-like">👍 喜欢</button>
</div>
{% endblock %}

{% block scripts %}
<script>
document.addEventListener('DOMContentLoaded', function() {
    const allPhotos = document.querySelectorAll('.dog-photo');
    let currentIndex = 0;

    // 显示当前索引对应的图片,隐藏其他
    function showCurrent() {
        allPhotos.forEach((photo, index) => {
            photo.classList.toggle('active', index === currentIndex);
        });
    }

    // 切换到下一张
    function nextPhoto() {
        currentIndex++;
        // 到最后一张后重置到开头,也可以改成提示结束
        if (currentIndex >= allPhotos.length) {
            alert('所有狗狗都看完啦!');
            currentIndex = 0;
        }
        showCurrent();
    }

    // 绑定按钮点击事件
    document.getElementById('btn-like').addEventListener('click', nextPhoto);
    document.getElementById('btn-dislike').addEventListener('click', nextPhoto);
});
</script>
{% endblock %}

方案二:后端API配合(支持记录评分)

如果需要把用户的评分保存到数据库,避免重复评分,就用这个方案,通过AJAX请求获取下一张未评分的图片。

1. 后端修改

首先确保数据库有ratings表(可自行创建:CREATE TABLE ratings (id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER, photo_id INTEGER, rating TEXT);),然后添加两个接口:

# 获取下一张未评分的图片
@app.route("/get_next_photo", methods=["GET"])
@login_required
def get_next_photo():
    try:
        conn = sqlite3.connect('dogs.db')
        cursor = conn.cursor()
        # 先查用户没评过分的图片
        cursor.execute("""
            SELECT id, photo_address FROM photos 
            WHERE id NOT IN (SELECT photo_id FROM ratings WHERE user_id = ?)
            LIMIT 1
        """, (session['user_id'],))
        photo = cursor.fetchone()
    except sqlite3.Error as er:
        print('SQLite error:', er)
        photo = None
    finally:
        conn.close()
    
    if photo:
        return jsonify({"photo_id": photo[0], "photo_url": photo[1]})
    else:
        return jsonify({"photo_url": None})

# 提交评分
@app.route("/submit_rating", methods=["POST"])
@login_required
def submit_rating():
    photo_id = request.form.get("photo_id")
    rating = request.form.get("rating")
    
    if not photo_id or not rating:
        return jsonify({"success": False})
    
    try:
        conn = sqlite3.connect('dogs.db')
        cursor = conn.cursor()
        cursor.execute("""
            INSERT INTO ratings (user_id, photo_id, rating)
            VALUES (?, ?, ?)
        """, (session['user_id'], photo_id, rating))
        conn.commit()
    except sqlite3.Error as er:
        conn.rollback()
        print('SQLite error:', er)
        return jsonify({"success": False})
    finally:
        conn.close()
    
    # 提交后直接返回下一张图片
    return get_next_photo()

同时修改原来的arena路由,只渲染空页面,图片通过JS加载:

@app.route("/arena", methods=["GET", "POST"])
@login_required
def arena():
    return render_template("arena.html")

2. 前端修改(arena.html)

{% extends "layout.html" %}

{% block title %}
    Arena
{% endblock %}

{% block head %}
<style>
#dog-photo {
    display: block;
    margin: 0 auto;
    max-width: 80%;
    max-height: 60vh;
}
.rating-buttons {
    margin-top: 20px;
    text-align: center;
}
.rating-buttons button {
    padding: 10px 24px;
    font-size: 18px;
    margin: 0 12px;
    cursor: pointer;
    border: none;
    border-radius: 8px;
}
#btn-like {
    background-color: #4CAF50;
    color: white;
}
#btn-dislike {
    background-color: #f44336;
    color: white;
}
</style>
{% endblock %}

{% block main %}
<div id="photo-container">
    <img id="dog-photo" alt="加载中..." src="">
</div>

<div class="rating-buttons">
    <button id="btn-dislike">👎 不喜欢</button>
    <button id="btn-like">👍 喜欢</button>
</div>
{% endblock %}

{% block scripts %}
<script>
let currentPhotoId;

// 加载下一张图片
function loadNextPhoto() {
    fetch("/get_next_photo")
        .then(res => res.json())
        .then(data => {
            if (data.photo_url) {
                currentPhotoId = data.photo_id;
                document.getElementById("dog-photo").src = data.photo_url;
            } else {
                alert("所有狗狗都看完啦!");
                document.getElementById("photo-container").style.display = "none";
            }
        });
}

// 提交评分
function sendRating(rating) {
    fetch("/submit_rating", {
        method: "POST",
        headers: {
            "Content-Type": "application/x-www-form-urlencoded"
        },
        body: `photo_id=${currentPhotoId}&rating=${rating}`
    })
    .then(res => res.json())
    .then(data => {
        if (data.success !== false) {
            if (data.photo_url) {
                currentPhotoId = data.photo_id;
                document.getElementById("dog-photo").src = data.photo_url;
            } else {
                alert("所有狗狗都看完啦!");
                document.getElementById("photo-container").style.display = "none";
            }
        } else {
            alert("评分提交失败,请重试");
        }
    });
}

// 页面加载时初始化
document.addEventListener("DOMContentLoaded", function() {
    loadNextPhoto();
    document.getElementById("btn-like").addEventListener("click", () => sendRating("like"));
    document.getElementById("btn-dislike").addEventListener("click", () => sendRating("dislike"));
});
</script>
{% endblock %}

内容的提问来源于stack exchange,提问作者jnel90

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 15:05:30