0

我正在尝试使用这样的 SelectMultiple 小部件呈现 postgres Arrayfield 值

在模型.py 中:

SLOT_CHOICES = (('A','Slot A'),('B','Slot B'),('C','Slot C'),('D','Slot D'),('E','Slot E'),('F','Slot F'),('G','Slot G'),('H','Slot H'),('P','Slot P'),('Q','Slot Q'),('R','Slot R'),('S','Slot S'),('T','Slot T'),)
core_slots = ArrayField(models.CharField(max_length=1,choices=SLOT_CHOICES),blank=True,null=True)

在 forms.py 中:

    self.fields['core_slots'].widget = forms.SelectMultiple(attrs={
            'placeholder': 'Choose slots',
            'class': 'multi-select-input',
        },choices=self.Meta.model.SLOT_CHOICES)

如果我选择一个选项并提交,然后尝试使用“实例”获取填写的表单,那么它可以正常工作并将先前选择的选项显示为“已选择”。但是如果我选择了多个选项,那么在提交所有选定的值时都会正确插入数据库,但是如果我尝试使用“实例”获取填写的表单,那么它不会显示任何已选择的选项。

ManyToManyField 不会出现此问题。

在模型.py 中:

past_courses = models.ManyToManyField(Course,blank=True)

在 forms.py 中:

    self.fields['past_courses'].queryset = Course.objects.filter(~Q(dept=self.instance.dept)).order_by('name')
    self.fields['past_courses'].widget.attrs.update({
            'placeholder': 'Choose past courses',
            'class': 'multi-select-input',
        })

这个工作正常。只有使用 SelectMultiple 小部件呈现的 ArrayField 存在问题。我想在模板中显示提交的选项,有没有办法解决这个问题,或者有没有其他方法可以在模板中显示选定的选项。

4

1 回答 1

3

我发现这似乎是一个问题,因为 SelectMultiple 小部件使用 ChoiceWidget ,它有一个 format_value 方法,可以不正确地处理多个选择。至少这是在 Django 1.11 中。format_value 执行以下操作:

def format_value(self, value):
    """Return selected values as a list."""
    if value is None and self.allow_multiple_selected:
        return []
    if not isinstance(value, (tuple, list)):
        value = [value]
    return [force_text(v) if v is not None else '' for v in value]

如您所见,它应该将选定的值作为列表返回。但是如果它不是元组或列表,则运行的代码是错误的。它只是本质上使值中的项目成为列表中的单个条目。因此,当您选择了多个项目时,例如“A”、“B”和“C”——它们以“A、B、C”的形式通过这个 format_value 函数——这实际上只是使它成为 ['A,B, C'] - 这是错误的。它需要是 ['A', 'B', 'C']。所以我只是输入代码来覆盖这个函数,如下所示:

def format_value(self, value):
    """Return selected values as a list."""
    if value is None and self.allow_multiple_selected:
        return []
    if not isinstance(value, (tuple, list)):
        # This means it should be a comma delimited list of items so parse it
        value = value.split(',')

    return [force_text(v) if v is not None else '' for v in value]

现在这对我来说似乎很好用。我在 Django 1.11 上测试了选择单个项目、多个项目和 NO 项目以及正确保存到数据库中的所有内容,并且也很好地显示在 Django Admin 上。希望这可以帮助。

于 2018-11-08T21:56:34.820 回答