传递给模板的 Django 对象 id 在视图函数中并不相同

问题描述 投票:0回答:1

当我提交表单时,视图函数内的问题 id 与 request.POST 中的问题 id 不匹配。

提交from时,下面视图函数的打印语句为:

问题_4 问题_5

在 request.POST 中,id 是 15 和 17,在视图中是 4、5。 每次我提交表单时,ID 都不匹配。

查看:

@login_required
def quiz_view(request):
    questions = QuizQuestion.objects.order_by('?')[:2]

    user = request.user

    if request.method == 'POST':
        print(request.POST)
        for question in questions:
            input_name = f"question_{question.id}"
            print(input_name)
            option_selected = request.POST.get(input_name)
            if option_selected:
                # Check if the user has already responded to this question
                existing_response = QuizUserResponse.objects.filter(user=user, question=question).first()
                if existing_response:
                    # Update existing response
                    existing_response.response_text = getattr(question, option_selected)
                    existing_response.save()
                else:
                    # Create new response
                    QuizUserResponse.objects.create(user=user, question=question, response_text=getattr(question, option_selected))
        return redirect('users:gaming_quiz')
    else:
        context = {
            "questions": questions,
        }
        return render(request, 'general/quiz_template.html', context)

HTML:

<form method="post">
    {% csrf_token %}
    {% for question in questions %}
    <div>
        <label class="question">{{ question.question_text }}</label>
        <ul class="errors">
            {% for error in form.errors %}
                <li>{{ error }}</li>
            {% endfor %}
        </ul>
        <div>
            <label class="form-check-inline">
                <input type="radio" name="question_{{ question.id }}" value="option1"> {{ question.option1 }}
            </label>
            <label class="form-check-inline">
                <input type="radio" name="question_{{ question.id }}" value="option2"> {{ question.option2 }}
            </label>
            <label class="form-check-inline">
                <input type="radio" name="question_{{ question.id }}" value="option3"> {{ question.option3 }}
            </label>
            <label class="form-check-inline">
                <input type="radio" name="question_{{ question.id }}" value="option4"> {{ question.option4 }}
            </label>
        </div>
    </div>
    {% endfor %}
    <button type="submit">Submit</button>
</form>
python html django
1个回答
0
投票

这并不奇怪,你再次提交到视图,在那里你再次从数据库中查询两个随机

QuizQuestion
,但不能保证这些与GET请求相同,在事实上,这种情况发生的可能性非常

因此,如果发出 POST 请求,您应该获取 id 出现在

QuizQuestion
中的
request.POST
,所以相反的方式:

@login_required
def quiz_view(request):
    user = request.user
    if request.method == 'POST':
        question_ids = [
            key[9:] for key in request.POST if key.startswith('question_')
        ]
        questions = QuizQuestion.objects.filter(pk__in=question_ids)
        for question in questions:
            input_name = f"question_{question.id}"
            print(input_name)
            option_selected = request.POST.get(input_name)
            if option_selected:
                existing_response = QuizUserResponse.objects.filter(
                    user=user, question=question
                ).first()
                if existing_response:
                    # Update existing response
                    existing_response.response_text = getattr(
                        question, option_selected
                    )
                    existing_response.save()
                else:
                    # Create new response
                    QuizUserResponse.objects.create(
                        user=user,
                        question=question,
                        response_text=getattr(question, option_selected),
                    )
        return redirect('users:gaming_quiz')
    else:
        questions = QuizQuestion.objects.order_by('?')[:2]
        context = {
            'questions': questions,
        }
        return render(request, 'general/quiz_template.html', context)

注意:允许

getattr(…)
 [python-doc] 使用属性的任意(用户指定)值通常(非常)不安全:它允许用户获取您想要的敏感数据隐藏。您可能想检查如何限制选项以提高安全性。

© www.soinside.com 2019 - 2024. All rights reserved.