代码之家  ›  专栏  ›  技术社区  ›  Natim

如何将optgroups添加到django ModelMultipleChoiceField?

  •  2
  • Natim  · 技术社区  · 14 年前

    ModelMultipleChoiceField 分类列表。 我想使用 Category.group 现场。

    choices 在init函数中,它将使

    class CategoriesField(forms.ModelMultipleChoiceField):
        def __init__(self, queryset, **kwargs):
            super(forms.ModelMultipleChoiceField, self).__init__(queryset, **kwargs)
            self.queryset = queryset.select_related()
            self.to_field_name=None
    
            group = None
            list = []
            self.choices = []
    
            for category in queryset:
                if not group:
                    group = category.group
    
                if group != category.group:
                    self.choices.append((group.title, list))
                    group = category.group
                    list = [(category.id, category.name)]
                else:
                    list.append((category.id, category.name))
            try:
                self.choices.append((group.title, list))
            except:
                pass
    

    但是 ModelChoiceIterator self.choices 中设置的信息 __init__

    2 回复  |  直到 14 年前
        1
  •  1
  •   Natim    14 年前

    实际上,它就像我刚才解释的那样工作,但不要忘记这一部分:

    class ProfilForm(ModelForm):
        categories  = CategoriesField(queryset=Category.objects.all().order_by('group'), label=_(u'Catégories'))
    
        2
  •  1
  •   ChrisRob lechup    5 年前

    你的代码对我有用,谢谢!也可以与一起使用模型.ManyToManyField其他人可能也会感兴趣:

    from django.db import models
    
    class CustomManyToManyField(models.ManyToManyField):
        def formfield(self, *args, **kwargs):
            kwargs["form_class"] = CategoriesField
            return super().formfield(**kwargs)
    

    我也有同样的缓存错误,并且通过将整个选项更新放在迭代器中来修复它:

    class CustomModelChoiceIterator(forms.models.ModelChoiceIterator):
        def __iter__(self):
            group = ""
            subgroup = []
            for category in self.queryset:
                if not group:
                    group = category.group
    
                if group != category.group:
                    yield (group.title, subgroup)
                    group = category.group
                    subgroup = [(category.id, category.name)]
                else:
                    subgroup.append((category.id, category.name))
            yield (group.title, subgroup)
    
    
    class CategoriesField(forms.ModelMultipleChoiceField):
        iterator = CustomModelChoiceIterator
    
        3
  •  0
  •   Tim Tisdall    8 年前

    cache_choices=True ArticleMultipleChoiceField 然后缓存)。

    class ArticleChoiceIterator(forms.models.ModelChoiceIterator):
        def __iter__(self):
            if self.field.empty_label is not None:
                yield ("", self.field.empty_label)
            if self.field.cache_choices:
                if self.field.choice_cache is None:
                    last_profile = None
                    self.field.choice_cache = []
                    for article in self.queryset.all():
                        if last_profile != article.profile:
                            last_profile = article.profile
                            article_list = []
                            self.field.choice_cache.append((article.profile.name, article_list))
                        article_list.append(self.choice(article))
                for choice in self.field.choice_cache:
                    yield choice
            else:
                last_profile = None
                article_choices = []
                for article in self.queryset.all():
                    if last_profile != article.profile:
                        if article_choices:
                            yield (getattr(last_profile, 'name', ''), article_choices)
                        last_profile = article.profile
                        article_choices = []
                    article_choices.append(self.choice(article))
                if article_choices:
                    yield (getattr(last_profile, 'name', ''), article_choices)
    
    
    class ArticleMultipleChoiceField(forms.ModelMultipleChoiceField):
        # make sure queryset is ordered by profile first!
        def __init__(self, queryset, **kwargs):
            super(ArticleMultipleChoiceField, self).__init__(queryset, **kwargs)
            self.queryset = queryset.select_related('profile')
            self._choices = ArticleChoiceIterator(self)
    
    
    class PackageForm(forms.ModelForm):
        articles = ArticleMultipleChoiceField(
            queryset=Article.objects.order_by('profile__name', 'title')
        )