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

Django找不同游戏:POST请求无法正确获取异类图片ID问题

找不同游戏的ID匹配问题

我正在开发一款找不同游戏,向用户展示4张图片,其中1张为异类图片,用户选中异类图片时得分+1。当前遇到的问题是:向模板传递包含1张异类图片的4张图片后,模板中3张同类图片ID正确,但异类图片ID随机变化(期望保持其真实ID)。例如picture_ids为[1,3,4,6](6为异类图片ID),用户选中异类图片时,selected_picture_id应等于6,但实际获取到随机ID,甚至在提交用户选择前就出现随机ID的情况。

现有代码

view.py

def odd_one_out_game(request):
    # Get a random country
    country = random.choice(Country.objects.all())
    print("Selected country:", country)

    # Get three random pictures from the selected country
    pictures = list(Picture.objects.filter(country=country).order_by('?')[:3])
    print("Pictures from selected country:", pictures)

    # Get one random picture from a different country
    other_country = random.choice(Country.objects.exclude(pk=country.pk))
    other_picture = random.choice(Picture.objects.filter(country=other_country))
    other_picture_id = other_picture.id
    print(other_picture_id)
    print("Random picture from other country:", other_picture)

    # Add the other picture to the list of pictures
    pictures.append(other_picture)
    print("All pictures:", pictures)

    # Shuffle the pictures to mix up the order
    random.shuffle(pictures)
    print("Shuffled pictures:", pictures)
    #get the ids of the pictures
    picture_ids = [picture.id for picture in pictures]
    print("Picture IDs:", picture_ids)

    odd_score = request.session.get('odd_score', 0)
    total_guesses = request.session.get('total_guesses', 0)
    message = ""  # Initialize message variable
    print("Initial score:", odd_score, "Initial total guesses:", total_guesses)

    if request.method == 'POST':
        selected_picture_id = request.POST.get('odd_one_out')
        selected_picture = Picture.objects.get(id=selected_picture_id)
        total_guesses += 1
        print("Selected picture ID:", selected_picture_id)
        print("Selected picture:", selected_picture)
        print(selected_picture.country, other_country)
        if selected_picture.country != other_country:
            # Increase score by 1 if the selected picture is the odd one out
            odd_score += 1
            message = "Congratulations! You guessed the right answer."
            print("Score increased:", odd_score)
        else:
            message = "Sorry! You guessed the wrong answer."
            print("Score unchanged:", odd_score)

        # Update session with the new score
        request.session['odd_score'] = odd_score
        request.session['total_guesses'] = total_guesses
        print("Updated score:", odd_score, "Updated total guesses:", total_guesses)

    context = {
        'country': country,
        'pictures': pictures,
        'score': odd_score,
        'total_guesses': total_guesses,
        'message': message,
    }
    return render(request, 'odd_one_out_game.html', context)

odd_one_out_game.html

<form method="post">
        {% csrf_token %}
        {% for picture in pictures %}
            <input type="radio" name="odd_one_out" id="{{ picture.id }}" value="{{ picture.id }}">
            <label for="{{ picture.id }}"><img src="{{ picture.image.url }}" alt="{{ country.name }}"></label>
        {% endfor %}
        <button type="submit">Submit</button>
    </form>

问题根源

每次请求(不管是首次加载页面的GET请求,还是提交答案的POST请求)都会重新执行随机选图、生成异类图片的逻辑,导致POST请求时的other_country和other_picture是全新生成的,和用户看到的那组图片完全无关;同时页面加载时的异类ID也会因为重复执行逻辑出现不一致。

修复方案

将题目生成逻辑限制在首次GET请求时执行,把关键数据存入session,POST请求时从session读取数据进行判断,避免重复生成。

修改后的view.py代码

def odd_one_out_game(request):
    odd_score = request.session.get('odd_score', 0)
    total_guesses = request.session.get('total_guesses', 0)
    message = ""

    # 仅在首次加载或session无当前题目数据时生成新题目
    if request.method == 'GET' or 'current_pictures' not in request.session:
        # 随机选目标国家
        country = random.choice(Country.objects.all())
        # 获取3张目标国家的图片
        pictures = list(Picture.objects.filter(country=country).order_by('?')[:3])
        # 获取异类图片(来自其他国家)
        other_country = random.choice(Country.objects.exclude(pk=country.pk))
        other_picture = random.choice(Picture.objects.filter(country=other_country))
        pictures.append(other_picture)
        random.shuffle(pictures)
        
        # 将题目关键数据存入session
        request.session['current_pictures'] = [pic.id for pic in pictures]
        request.session['correct_country_id'] = other_country.pk
        request.session['current_country_id'] = country.pk

    # 从session读取当前题目数据
    picture_ids = request.session['current_pictures']
    correct_country_id = request.session['correct_country_id']
    current_country_id = request.session['current_country_id']
    # 按session中存储的ID顺序获取图片对象(MySQL语法,其他数据库需调整)
    pictures = Picture.objects.filter(id__in=picture_ids).extra(
        select={'order': 'FIELD(id, {})'.format(','.join(map(str, picture_ids)))},
        order_by=['order']
    )
    current_country = Country.objects.get(pk=current_country_id)

    if request.method == 'POST':
        selected_picture_id = request.POST.get('odd_one_out')
        selected_picture = Picture.objects.get(id=selected_picture_id)
        total_guesses += 1

        # 判断选中的是否为异类图片
        if selected_picture.country.pk == correct_country_id:
            odd_score += 1
            message = "恭喜你!答对了!"
        else:
            message = "抱歉,答错了。"

        # 更新分数统计
        request.session['odd_score'] = odd_score
        request.session['total_guesses'] = total_guesses
        # 清除当前题目数据,下次请求生成新题目
        del request.session['current_pictures']
        del request.session['correct_country_id']
        del request.session['current_country_id']

    context = {
        'country': current_country,
        'pictures': pictures,
        'score': odd_score,
        'total_guesses': total_guesses,
        'message': message,
    }
    return render(request, 'odd_one_out_game.html', context)

关键修改说明

  • 题目生成逻辑仅在首次GET请求或session无数据时执行,确保每组题目只生成一次
  • 将图片ID列表、异类图片所属国家ID存入session,POST请求时直接读取,避免重新生成数据
  • POST提交后清除session中的当前题目数据,保证下次请求加载新题目
  • 使用FIELD(id, ...)语法保持图片顺序与session中存储的一致(若使用PostgreSQL,需替换为POSITION(id::text IN '{}').format(','.join(map(str, picture_ids))))

模板代码无需修改,保持原代码即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 05:26:09