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

Django模型表单验证失败:category字段提示无效选项求助

解决Django表单category字段验证失败问题

提交表单创建Listing实例时,触发category字段验证错误,错误信息:

Select a valid choice. 7 is not one of the available choices.

相关代码

models.py中的Listing模型

class Listing(models.Model):
    title = models.CharField(max_length=64)
    description = models.TextField()
    image = models.ImageField(blank=True)
    categories = ((1,"Clothing/Footwear"), (2,"Books"), (3,"Electronics"), (4,"Cosmetics"), (5,"Toys"), (6,"Home/Garden"), (7,"Sport/Leisure"))
    category = models.CharField(choices=categories, max_length=2)
    starting_price = models.DecimalField(decimal_places=2, max_digits=10)
    lister = models.ForeignKey(User, on_delete=models.CASCADE, related_name="selling")

表单类代码

class Listing_Form(forms.ModelForm):
    class Meta:
        model = Listing
        fields = "__all__"

views.py中的create函数

def create(request):
    if request.method == "POST":
        form = Listing_Form(request.POST)
        print(form.errors)
        if form.is_valid():
            print('valid')
            form.save()
            return HttpResponseRedirect(reverse("index"))
        else:
            print('invalid')
    else:
        form = Listing_Form()

问题原因

category字段定义为CharField,但choices元组中的选项键是整数类型(如1、7)。表单提交时,前端传递的是字符串格式的选项值(如"7"),Django会将提交的字符串与choices中的整数键做匹配,类型不匹配导致验证失败。

解决方案

提供两种可选修复方式:

方案一:修改字段类型为IntegerField(推荐)

将category字段改为整数类型,与choices中的键类型匹配:

class Listing(models.Model):
    # 其他字段保持不变
    categories = ((1,"Clothing/Footwear"), (2,"Books"), (3,"Electronics"), (4,"Cosmetics"), (5,"Toys"), (6,"Home/Garden"), (7,"Sport/Leisure"))
    category = models.IntegerField(choices=categories)

Django会自动将表单提交的字符串转换为整数进行验证,匹配后即可通过。

方案二:修改choices的键为字符串类型

如果不想修改字段类型,将categories中的键改为字符串:

class Listing(models.Model):
    # 其他字段保持不变
    categories = (
        ("1","Clothing/Footwear"), 
        ("2","Books"), 
        ("3","Electronics"), 
        ("4","Cosmetics"), 
        ("5","Toys"), 
        ("6","Home/Garden"), 
        ("7","Sport/Leisure")
    )
    category = models.CharField(choices=categories, max_length=2)

此时提交的字符串值与choices中的字符串键一致,验证可通过。

额外优化建议

当前表单包含lister字段,这是关联用户的外键,不应让前端用户选择。建议修改表单排除该字段,在视图中手动设置当前登录用户:

  1. 修改表单类:
class Listing_Form(forms.ModelForm):
    class Meta:
        model = Listing
        exclude = ["lister"]
  1. 修改views.py的create函数:
def create(request):
    if request.method == "POST":
        form = Listing_Form(request.POST)
        print(form.errors)
        if form.is_valid():
            print('valid')
            # 手动设置当前登录用户为lister
            listing = form.save(commit=False)
            listing.lister = request.user
            listing.save()
            return HttpResponseRedirect(reverse("index"))
        else:
            print('invalid')
    else:
        form = Listing_Form()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 09:30:46