我正在制作按类别分类的分类目录。
但是,当我提交表单时,收到以下错误消息:
Caught ValueError while rendering: Cannot assign "u'9'": "Classified.category" must be a "Category" instance.
我相信这是因为Django需要一个Category对象而不是一个对应于所选类别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()会破坏我的表单验证,我不知道如何解决我的问题。
如果我可以指出我错在哪里以及如何解决这个问题,那就太棒了。
提前感谢您的帮助。
答案 0 :(得分:1)
快速解决方案是手动保存类别
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 :(得分:0)
您可以而且应该仍然使用ModelChoiceField。可以在表单类的 init 方法中修改选项列表 - 即
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包。看起来你可能正在重新发明轮子。