【问题标题】:Select all choices in a ManyToManyField by default默认选择 ManyToManyField 中的所有选项
【发布时间】:2014-12-22 01:59:24
【问题描述】:

默认情况下是否有可能在 Django 中的 ManyToManyField 生成的多选中选择所有选项?

添加的所有新项目都应在视图中预先选择所有选项(添加AnotherEntity 的新项目时也是如此)。

class AnotherEntity(models.Model):
    name = models.CharField()

class SomeEntity(models.Model): 
    anotherEntity = models.ManyToManyField(AnotherEntity)

在上面的示例中,我希望在所有新项目中选择anotherEntity 中的所有选项。

【问题讨论】:

    标签: django django-models django-forms django-suit


    【解决方案1】:

    只需继承SelectMultiple 小部件并覆盖: 1)render_option 以呈现所有选定的内容; 2) render_options 控制我们在哪里渲染所有选定的以及默认的渲染位置。

    class CustomSelectMultiple(SelectMultiple):
        def render_options(self, choices, selected_choices):
            if not selected_choices:
                # there is CreatView and we have no selected choices - render all selected
                render_option = self.render_option
            else:
                # there is UpdateView and we have selected choices - render as default
                render_option = super(CustomSelectMultiple, self).render_option
    
            selected_choices = set(force_text(v) for v in selected_choices)
            output = []
            for option_value, option_label in chain(self.choices, choices):
                if isinstance(option_label, (list, tuple)):
                    output.append(format_html('<optgroup label="{0}">', force_text(option_value)))
                    for option in option_label:
                        output.append(render_option(selected_choices, *option))
                    output.append('</optgroup>')
                else:
    
                    output.append(render_option(selected_choices, option_value, option_label))
            return '\n'.join(output)
    
        def render_option(self, selected_choices, option_value, option_label):
            option_value = force_text(option_value)
            selected_html = mark_safe(' selected="selected"')
    
            return format_html('<option value="{0}"{1}>{2}</option>',
                               option_value,
                               selected_html,
                               force_text(option_label))
    

    然后在表单中将小部件设置为您的字段:

    class SomeEntityModelForm(forms.ModelForm):
        def __init__(self, *args, **kwargs):
            super(SomeEntityModelForm, self).__init__(*args, **kwargs)
    
            self.base_fields['anotherEntity'].widget = CustomSelectMultiple()
    
        class Meta:
            model = SomeEntity
    

    【讨论】:

    【解决方案2】:

    你可以override这样保存模型的方法:

    class SomeEntity(models.Model): 
        anotherEntity = models.ManyToManyField(AnotherEntity)    
    
        def save(self, *args, **kwargs):
            choices = AnotherEntity.objects.all()
            for choice in choices:
                self.anotherentity.add(choice)
            super(SomeEntity, self).save(*args, **kwargs)
    

    【讨论】:

    • 无论最终用户在渲染页面上的更改如何,它都会保存所有选择
    • 我只想选择首字母。如果用户取消选择它应该保持这样。
    猜你喜欢
    • 2019-01-21
    • 1970-01-01
    • 1970-01-01
    • 2014-03-27
    • 2017-12-18
    • 2016-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多