2011-12-29 5 views
2

カテゴリ別に分類されたカタログを作成しています。私は自分のフォームを送信する際ChoiceFieldでフォームの値を確認できません

はしかし、私は、次のエラーメッセージが表示されます。

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

私はDjangoが代わりに選択したカテゴリIDに対応し、簡単な整数のCategoryオブジェクトを想定しているため、これがあると信じています。

ここに私がシステムを書いた方法があります: 分類は1つのカテゴリにリンクしています。 カテゴリシステムは、親カテゴリと子カテゴリのリストを持つ階層型です。私は、次のマネージャ作成

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のフォームは、次が含まれてい

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

だから私は、次のモデルを持っている: は、たとえば、私はこのようなものを持っています:

class ClassifiedForm(forms.ModelForm): 
    # [...] 

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

カテゴリ= forms.ModelChoiceField(Category.objects.all())を使用するとすべて正常に機能しますが、<select>フィールドが<optgroup>のリストでどのように表示されるかを制御する必要があります。これはなぜcategoriesTree()を使用するのですか 残念ながら、CategoryManager.categoryTree()を使用するとフォームの検証が壊れてしまい、問題を解決する方法がわかりません。

私はどこが間違っていたか、どのように修正できるかを指摘できれば、それはすばらしいことになります。

ご協力いただきありがとうございます。

+0

pythonタグが追加されました。 – lig

答えて

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 
0

あなたは、まだModelChoiceFieldを使用する必要がありますすることができ、カテゴリに保存することです。また、あなたがdjango-mpttパッケージを注意深く見なければならない、すなわち

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() 

- 選択肢のリストは、フォームクラスののinit方法で変更することができます。あなたがここで車輪を再発明するかもしれないように見えます。

+0

'categoryTree()'がquerysetを返すとうまくいく可能性があります。しかし、それはしません。 – DrTyrsa

+0

彼が投稿したものから、categoryTreeは選択肢のタプルを返します。ご覧のとおり、カテゴリフィールドのchoices属性に割り当てています。私はqueryset属性に対してcategoryTreeObjectsという別の関数(彼が書く必要がある)を考案しました。 –

+0

これはうまくいくが、2つの "並列"機能は維持するのに最適ではない。そして、BTWの 'queryset' attrは妥当性検証の目的だけではなく、' save'ロジックもそれに重きを置いています。だから私は 'ModelForm'が好きではありません。 – DrTyrsa

関連する問題