Не удается проверить значения формы с помощью ChoiceField - PullRequest
2 голосов
/ 29 декабря 2011

Я работаю над каталогом классифицированных сгруппированных по категориям.

Однако, когда я отправляю свою форму, я получаю следующее сообщение об ошибке:

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

Я полагаю, что это потому, что Djangoожидает объекты категории вместо простого целого числа, которое соответствует выбранному идентификатору категории.

Вот как я написал систему: классификация связана с одной категорией.Система категорий является иерархической с родительской категорией и списком дочерних категорий.Например, у меня есть что-то вроде этого:

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 () нарушает мою проверку формы, и я не знаю, как исправить мою проблему.

Если бы я мог указать, где я был неправ, и как я могу это сделатьисправить это, это было бы здорово.

Заранее спасибо за вашу помощь.

Ответы [ 2 ]

1 голос
/ 29 декабря 2011

Быстрое решение - сохранить категорию вручную

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 голосов
/ 29 декабря 2011

Вы можете и должны использовать 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 . Похоже, вы изобретаете колесо здесь.

...