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字段,这是关联用户的外键,不应让前端用户选择。建议修改表单排除该字段,在视图中手动设置当前登录用户:
- 修改表单类:
class Listing_Form(forms.ModelForm): class Meta: model = Listing exclude = ["lister"]
- 修改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
相关产品推荐
相关产品推荐

