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

Django表单条件判断异常:所有选项均返回同一推荐结果

问题:Django测验程序始终返回第一个推荐结果

我正在学习Django,开发一个根据用户兴趣推荐编程语言的简易测验程序:

  • 包含3个是/否问题;
  • 表单提交后通过if条件判断生成对应推荐。

预期示例:

  • 选是、是、是时,推荐"Javascript, HTML/CSS, React JS, Angular, Figma";
  • 选是、是、否时,推荐"HTML/CSS, Javascript, Flutter"。

但实际问题:无论选择哪种组合,程序始终返回第一个推荐结果。

补充排查:通过Answer.objects.all()能看到数据库中有True值,但在前端打印webdev、mobdev、uiux的类型时,始终显示False,同时疑惑若值全为False,为何不返回else分支的结果。


代码细节

models.py

from django.db import models

# Create your models here.
class User(models.Model):
    name = models.CharField(max_length=20)

    def __str__(self):
        return f"{self.name}"
    
class Answer(models.Model):
    name = models.ForeignKey(User, on_delete=models.CASCADE)
    webdev = models.BooleanField(default=True)
    mobdev = models.BooleanField(default=True)
    uiux = models.BooleanField(default=True)

    def __str__(self):
        return f"{self.name.name}, {self.webdev}, {self.mobdev}, {self.uiux}"

class Result(models.Model):
    name = models.ForeignKey(User, on_delete=models.CASCADE)
    response = models.CharField(max_length=50, default='Unidentified')

    def __str__(self):
        return f"{self.name.name} {self.response}"

forms.py

from django import forms

class Quizzes(forms.Form):
    CHOICES = [
        (True, 'Tertarik'),
        (False, 'Tidak Tertarik')
    ]
    name = forms.CharField(label='Siapakah nama anda?', max_length=20)
    wd = forms.ChoiceField(
        widget = forms.RadioSelect,
        choices = CHOICES,
        label = "Apakah anda tertarik dengan Web Development?"
    )
    md = forms.ChoiceField(
        widget = forms.RadioSelect,
        choices = CHOICES,
        label = "Apakah anda tertarik dengan Mobile Development?"
    )
    ix = forms.ChoiceField(
        widget = forms.RadioSelect,
        choices = CHOICES,
        label = "Apakah anda tertarik dengan UI / UX?"
    )

views.py

from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
from . forms import *
from . models import *
# Create your views here.

def home(response):
    if response.method == 'POST':
        form = Quizzes(response.POST)
        if form.is_valid():
            name = form.cleaned_data['name']
            wd = form.cleaned_data['wd']
            md = form.cleaned_data['md']
            ix = form.cleaned_data['ix']

            q = User.objects.create(name=name)
            q.save()
            q.answer_set.create(webdev=wd, mobdev=md, uiux=ix)

            if wd and md and ix:
                q.result_set.create(response='Javascript, HTML/CSS, React JS, Angular, Figma')
            elif wd and not md and not ix:
                q.result_set.create(response='Javascript, HTML/CSS, PHP')
            elif not wd and md and not ix:
                q.result_set.create(response='Java, Kotlin, Flutter, Swift')
            elif not wd and not md and ix:
                q.result_set.create(response='Canva, Figma, Adobe')
            elif not wd and md and ix:
                q.result_set.create(response='Swift, Kotlin, Flutter, Java')
            elif wd and not md and ix:
                q.result_set.create(response='HTML/CSS, Javascript, Canva, React, Figma')
            elif wd and md and not ix:
                q.result_set.create(response='HTML/CSS, Javascript, Flutter')
            else:
                q.result_set.create(response='None of our recommendations match your interest')

        return HttpResponseRedirect(f"/{q.id}")
    else:
        form = Quizzes()
    return render(response, 'home.html', {'form' : form})

def result(response, id):
    u = User.objects.get(id=id)
    a = u.answer_set.all()
    r = u.result_set.all()
    
    return render(response, 'result.html', {'u' : u, 'r' : r, 'a' : a})

result.html

{% extends 'base.html' %}

{% block result %}
    {{ u.name }}
    <br>
    {{ a }}
    <br>
    {{ u.result_set.all }}

{% endblock %}

问题根源

问题出在表单的ChoiceField处理逻辑:Django的ChoiceField默认会将选中值转换为字符串类型,而非布尔值。你在CHOICES中定义的(True, 'Tertarik'),提交后form.cleaned_data['wd']拿到的是字符串'True'或'False',不是原生布尔值True/False。

在Python中,任何非空字符串都会被判定为True,所以wd and md and ix永远为真,导致程序始终触发第一个判断分支。


修复方案

方案1:改用BooleanField搭配单选组件

修改forms.py,将三个问题字段替换为BooleanField,并绑定单选框:

from django import forms

class Quizzes(forms.Form):
    name = forms.CharField(label='Siapakah nama anda?', max_length=20)
    wd = forms.BooleanField(
        widget=forms.RadioSelect(choices=[(True, 'Tertarik'), (False, 'Tidak Tertarik')]),
        label="Apakah anda tertarik dengan Web Development?",
        required=True
    )
    md = forms.BooleanField(
        widget=forms.RadioSelect(choices=[(True, 'Tertarik'), (False, 'Tidak Tertarik')]),
        label="Apakah anda tertarik dengan Mobile Development?",
        required=True
    )
    ix = forms.BooleanField(
        widget=forms.RadioSelect(choices=[(True, 'Tertarik'), (False, 'Tidak Tertarik')]),
        label="Apakah anda tertarik dengan UI / UX?",
        required=True
    )

方案2:手动转换字符串为布尔值

如果坚持使用ChoiceField,在views.py中对清洗后的数据做类型转换:

# 在form.is_valid()代码块内修改
wd = form.cleaned_data['wd'] == 'True'
md = form.cleaned_data['md'] == 'True'
ix = form.cleaned_data['ix'] == 'True'

额外优化建议

  1. 模型中的Answer和Result可以合并,减少数据冗余;
  2. User.objects.create()会自动保存对象,无需额外调用q.save();
  3. 优化结果页面展示,避免直接打印QuerySet:
{% extends 'base.html' %}

{% block result %}
    <h3>Hasil untuk {{ u.name }}</h3>
    <p>Pilihan Anda:</p>
    {% for answer in a %}
        <ul>
            <li>Web Development: {{ answer.webdev|yesno:"Tertarik,Tidak Tertarik" }}</li>
            <li>Mobile Development: {{ answer.mobdev|yesno:"Tertarik,Tidak Tertarik" }}</li>
            <li>UI/UX: {{ answer.uiux|yesno:"Tertarik,Tidak Tertarik" }}</li>
        </ul>
    {% endfor %}
    <p>Rekomendasi:</p>
    {% for result in r %}
        <p>{{ result.response }}</p>
    {% endfor %}
{% endblock %}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 14:42:15