Django实现ProductForm级联Category/Subcategory筛选时报NoneType属性错误
报错根因
- 空对象报错触发逻辑:在
ProductForm的__init__方法中,编辑实例分支代码存在字段名错位问题。该段代码本应为subcategory字段加载可选查询集,却错误指向category字段;同时访问新建产品页面时,self.instance是未关联数据库记录的空Product对象,其category外键属性默认值为None,代码此时试图对None调用list_of_subcategories属性,直接抛出空对象属性错误。 - 语法错误:代码中使用
self.fields('subcategory')调用字典对象,self.fields为类字典结构,需用方括号取值,圆括号调用会触发“对象不可调用”的运行错误。 - 查询逻辑错位:POST请求分支中,本该给
subcategory字段设置按分类过滤的查询集,却错误使用Category.objects.filter(category_id=category_id)赋值——Category模型不存在category_id字段,返回的查询集完全不符合业务预期。 - 提交失败根源:初始化时将
subcategory的查询集设为空集,但在回显编辑数据、处理POST校验时,没有正确加载当前选中分类对应的子分类可选范围,表单校验会将用户选择的subcategory值判定为不在可选列表内,直接拦截提交流程。 - 模型层潜在隐患:
Category模型中slug字段的默认值写法为default=slugify(name),类定义阶段name变量尚未初始化,执行时会触发NameError,无法正常完成数据库迁移。
修复方案
修正Category模型的slug生成逻辑
将slug生成逻辑从类定义阶段的固定执行改为实例保存时动态触发,避免初始化报错:
class Category(models.Model): name = models.CharField(max_length=100) slug = models.SlugField(unique=True, blank=True) def save(self, *args, **kwargs): if not self.slug: self.slug = slugify(self.name) super().save(*args, **kwargs) class Meta: verbose_name = 'category' verbose_name_plural = 'categories' def __str__(self): return self.name
重写ProductForm的初始化逻辑
修正语法、空值判断、字段对应关系、查询逻辑的全部问题:
class ProductForm(ModelForm): class Meta: model = Product fields = [ 'sku', 'name', 'category', 'subcategory', 'short_description', 'description', 'price', ] def __init__(self, *args, **kwargs): super().__init__(*args,**kwargs) # 初始状态下子分类可选范围为空,等待用户选择分类后联动加载 self.fields['subcategory'].queryset = SubCategory.objects.none() # 处理POST提交场景 if 'category' in self.data: try: category_id = int(self.data.get('category')) # 直接从SubCategory表过滤当前选中分类下的所有子项作为可选值 self.fields['subcategory'].queryset = SubCategory.objects.filter(category_id=category_id).order_by('name') except (ValueError, TypeError): pass # 处理编辑已有产品的场景:加载当前产品关联分类下的所有子分类作为可选值 elif self.instance.pk and self.instance.category: self.fields['subcategory'].queryset = self.instance.category.list_of_subcategories.order_by('name')
修正要点:
- 增加
self.instance.category空值判断,避免对未关联分类的空实例调用属性 - 修正字段赋值方向,将原来错误指向category字段的赋值逻辑,调整为给subcategory字段设置正确的查询集
- 修正
self.fields的方括号取值语法,避免对象调用错误 - 修正POST分支的查询逻辑,不再错误查询Category模型,直接从SubCategory表获取对应分类的子项数据
联动功能收尾检查
现有loadSubcategory视图逻辑符合业务需求,只要确保前端form标签设置了指向该视图的正确data-subcategories-url属性,就能正常实现分类选择后联动加载子分类下拉选项。
由于初始状态下子分类查询集为空,用户未选择分类直接提交时,表单会自动拦截提示,避免无效数据入库。
内容的提问来源于stack exchange,提问作者kimnluna
相关产品推荐
相关产品推荐

