首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法使用ChoiceField检查表单值

无法使用ChoiceField检查表单值
EN

Stack Overflow用户
提问于 2011-12-29 20:07:12
回答 2查看 396关注 0票数 2

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

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

代码语言:javascript
复制
Caught ValueError while rendering: Cannot assign "u'9'": "Classified.category" must be a "Category" instance.

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

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

代码语言:javascript
复制
Electronics
    |-- IPad
    |-- IPods
    |-- ...

因此,我有以下模型:

代码语言:javascript
复制
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')

我创建了以下管理器:

代码语言:javascript
复制
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表单包含以下内容:

代码语言:javascript
复制
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()),一切正常,但是我需要用一个<optgroup>列表来控制<select>字段的显示方式。这就是为什么使用categoryTree(),但不幸的是,使用CategoryManager.categoryTree()破坏了我的表单验证,并且我不知道如何解决我的问题。

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

提前感谢您的帮助。

EN

回答 2

Stack Overflow用户

发布于 2011-12-29 20:39:58

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

代码语言:javascript
复制
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
票数 1
EN

Stack Overflow用户

发布于 2011-12-29 20:47:21

您可以而且应该仍然使用ModelChoiceField。可以在form类的init方法中修改选项列表。

代码语言:javascript
复制
class ClassifiedForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(ClassifiedForm, self).__init__(*args, **kwargs)

        # Set the queryset for validation purposes. 
        # May not be necessary if categoryTree contains all categories
        self.fields['category'].queryset = Category.objects.categoryTreeObjects() 

        # Set the choices
        self.fields['category'].choices = Category.objects.categoryTree()

此外,您还应该仔细查看django-mptt包。看起来你可能是在重新发明轮子。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8667684

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档