Skip to main content
 首页 » 编程设计

python之无法使用 ChoiceField 检查表单值

2025年05月04日8zhujiabin

我正在制作按类别分组的分类目录。

但是当我提交表单时,我收到以下错误消息:

Caught ValueError while rendering: Cannot assign "u'9'": "Classified.category" must be a "Category" instance. 

我相信这是因为 Django 需要一个类别对象,而不是一个与所选类别 ID 相对应的简单整数。

下面是我写的系统: 分类链接到一个类别。 类别系统是分层的,具有父类别和子类别列表。 例如我有这样的东西:

Electronics 
    |-- IPad 
    |-- IPods 
    |-- ... 

所以我有以下模型:

class Category(BaseModel): 
    # [...] 
    name = models.CharField(u'Name', max_length=50) 
    slug = AutoSlugField(populate_from='name', slugify=slugify, unique=True, 
        unique_with='name', max_length=255, default='') 
    parent = models.IntegerField(u'parent', max_length=10, null=False, 
            default=0) 
 
    objects = CategoryManager() 
 
    # [...] 
 
class Classified(BaseModel): 
    # [...] 
    category = models.ForeignKey(Category, related_name='classifieds') 

我创建了以下管理器:

class CategoryManager(Manager): 
    def categoryTree(self): 
        tree = self.raw("SELECT" 
            " P.id, P.name parent_name, P.slug parent_slug, P.id parent_id," 
            " C.name child_name, C.slug child_slug, C.id child_id" 
            " FROM classified_category C" 
            " LEFT JOIN classified_category P ON P.id = C.parent" 
            " WHERE C.parent <> 0" 
            " ORDER BY P.name, C.name;") 
 
        categoryTree = [] 
 
        current_parent_id = tree[0].parent_id 
        current_parent_name = tree[0].parent_name 
        option_list = [] 
 
        for c in tree: 
            if current_parent_id != c.parent_id: 
                categoryTree.append((current_parent_name, option_list)) 
                option_list = [] 
                current_parent_id = c.parent_id 
                current_parent_name = c.parent_name 
 
            option_list.append((c.child_id, c.child_name)) 
 
        categoryTree.append((current_parent_name, option_list)) 
 
        return category 

我的 Django 表单包含以下内容:

class ClassifiedForm(forms.ModelForm): 
    # [...] 
 
    category = forms.ChoiceField(label=u'Category', required=True, 
            choices=Category.objects.categoryTree(), widget=forms.Select()) 
    # [...] 

如果我使用 category = forms.ModelChoiceField(Category.objects.all()) 一切正常,但我需要控制 <select> 的方式字段显示为 <optgroup> 的列表.这就是为什么使用 categoryTree() 但不幸的是,使用 CategoryManager.categoryTree() 破坏了我的表单验证,我不知道如何解决我的问题。

如果我能指出我错在哪里以及如何解决这个问题,那就太棒了。

预先感谢您的帮助。

请您参考如下方法:

快速解决方案是手动保存类别

class ClassifiedForm(forms.ModelForm): 
    # [...] 
 
    category = forms.ChoiceField(label=u'Category', required=True, 
            choices=Category.objects.categoryTree(), widget=forms.Select()) 
 
    class Meta: 
        exclude=('category',) 
 
    def save(self): 
        classified = super(ClassifiedForm, self).save(commit=False) 
        classified.category = Category.objects.get(id=self.cleaned_data['category']) 
        classified.save() 
        return classified