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

Python/Django中如何在GET和POST视图中使用同一随机生成的题目列表

问题解决方法

核心问题原因

当前代码每次触发trivia视图请求(不管是GET加载题目页,还是POST提交答案),都会重新执行随机抽样逻辑,两次拿到的题目子集完全不同,自然会出现答案和题目不匹配的问题。

方案一:使用Django Session存储抽题ID(推荐)

利用用户会话缓存本次随机抽取的题目ID列表,GET请求生成后存入服务端session,POST请求直接从session读取ID查询题目,无需重新随机抽题。服务端存储的ID用户无法篡改,可避免作弊问题。
修改后代码如下:

import random
from django.shortcuts import render
from .models import Trivia

def trivia(request):
    if request.method == 'POST':
        # 从session读取之前存入的题目ID列表
        random_trivia_id_list = request.session.get('random_trivia_ids')
        # 异常处理:session过期则跳转回答题页提示重试
        if not random_trivia_id_list:
            return render(request, "ColdBlooded/trivia.html", {"error": "答题超时,请重新开始"})
        trivia = Trivia.objects.filter(id__in=random_trivia_id_list)
        
        correct = 0
        incorrect = 0
        total = 0
        for t in trivia:
            user_answer = request.POST.get(t.question)
            if t.answer == user_answer:
                correct += 1
            else:
                incorrect += 1
            total += 1
        result = correct / total
        # 提交完成后清空session中的题目ID,避免用户下次答题复用同一套题
        del request.session['random_trivia_ids']
        return render(request, 'ColdBlooded/result.html', {
            "Incorrect": incorrect,
            "Correct": correct,
            "Total": total,
            "Trivia": trivia,
            "Result": result,
        })
    else:
        # GET请求生成随机题目ID,存入session
        trivia_id_list = Trivia.objects.values_list('id', flat=True)
        random_trivia_id_list = random.sample(list(trivia_id_list), min(len(trivia_id_list), 3))
        request.session['random_trivia_ids'] = random_trivia_id_list
        trivia = Trivia.objects.filter(id__in=random_trivia_id_list)
        return render(request, "ColdBlooded/trivia.html", {
            "Trivia": trivia
        })

Django默认已开启session功能,无需额外配置即可直接使用。

方案二:表单隐藏域传递抽题ID

无需依赖session,在GET渲染的答题页表单中新增隐藏输入框,将抽中的题目ID随用户答案一起提交,POST请求根据提交的ID查询对应题目即可。该方案支持用户多标签页同时答题互不干扰。
首先修改trivia.html的表单代码:

<form method="post">
    {% csrf_token %}
    <!-- 新增隐藏域存储所有抽中的题目ID -->
    {% for t in Trivia %}
    <input type="hidden" name="trivia_ids" value="{{ t.id }}">
    <!-- 原有题目、选项渲染代码保持不变 -->
    <p>{{ t.question }}</p>
    <input type="radio" name="{{ t.question }}" value="{{ t.option1 }}"> {{ t.option1 }}<br>
    <input type="radio" name="{{ t.question }}" value="{{ t.option2 }}"> {{ t.option2 }}<br>
    {% endfor %}
    <button type="submit">提交答案</button>
</form>

再修改视图代码的POST逻辑:

def trivia(request):
    if request.method == 'POST':
        # 从POST参数读取提交的所有题目ID
        random_trivia_id_list = request.POST.getlist('trivia_ids')
        trivia = Trivia.objects.filter(id__in=random_trivia_id_list)
        
        # 后续判分逻辑和原有代码完全一致
        correct = 0
        incorrect = 0
        total = 0
        for t in trivia:
            user_answer = request.POST.get(t.question)
            if t.answer == user_answer:
                correct += 1
            else:
                incorrect += 1
            total += 1
        result = correct / total
        return render(request, 'ColdBlooded/result.html', {
            "Incorrect": incorrect,
            "Correct": correct,
            "Total": total,
            "Trivia": trivia,
            "Result": result,
        })
    else:
        # GET逻辑和原有代码保持一致
        trivia_id_list = Trivia.objects.values_list('id', flat=True)
        random_trivia_id_list = random.sample(list(trivia_id_list), min(len(trivia_id_list),3))
        trivia = Trivia.objects.filter(id__in=random_trivia_id_list)
        return render(request, "ColdBlooded/trivia.html", {
            "Trivia": trivia
        })

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 20:00:02