Django字段,用于将列表存储为逗号分隔的字符串

时间:2017-07-23 15:48:29

标签: python django

我正在寻找一种解决方案,将Python列表存储为数据库中以逗号分隔的字符串。在做了一些研究并得出结论认为Django没有开箱即用之后,我决定自己写一下。

这是我提出的模范领域:

class CommaSeparatedStringsField(models.CharField):
    def from_db_value(self, value, *args):
        if not value:
            return []

        return value.split(',')

    def to_python(self, value):
        if isinstance(value, list):
            return value

        return self.from_db_value(value)

    def get_prep_value(self, value):
        return ','.join(value)

    def value_to_string(self, obj):
        return self.get_prep_value(self.value_from_object(obj))

    def formfield(self, **kwargs):
        defaults = {'form_class': ListField}
        defaults.update(kwargs)

        return models.Field.formfield(self, **defaults)

非常简单的东西,到目前为止,没有问题。

与此模型字段关联的表单字段和窗口小部件应为多选框。列表中的每个元素都是选择字段中的一个选项。

如果你想知道我为什么这么想,那就是Bootstrap Tags Input,这是一个用于输入标签的输入小部件。 (多个值)。这可以使用文本框,但我宁愿在Python中将此字段表示为列表。

现在有MultipleChoiceField(使用MultipleSelect小部件),但它有一个预定义的选项列表。这不是我想要的,在我的情况下,选项数据,而我并不关心所选的选项。

所以我写了一个自定义表单字段和小部件,它们是上述类的子类:

class ListWidget(SelectMultiple):
    def render_options(self, options):
        output = []

        for option_value, option_label in options:
            output.append(self.render_option([], option_value, option_label))

        return '\n'.join(output)


class ListField(MultipleChoiceField):
    widget = ListWidget

    def prepare_value(self, value):
        return [(x, x) for x in value]

我覆盖SelectMultiple的render_options()以将数据呈现为选项而不是预定义的选项,并且我覆盖了MultipleChoiceField的验证以删除选项check和prepare_value以将列表转换为列表元组(option_value和option_label)。

这在大多数情况下都有效。问题是当它被提交为空时它似乎没有保存字段,我不明白为什么。当我使用MultipleChoiceField本身而不是我写的自定义表单字段和小部件时,也会发生这种情况。

我尝试使用调试器缩小范围,但我无法找到这里发生的事情。我可以看到表单的已清理数据具有正确的值([],空列表),但是当保存该字段时,它具有旧值。

我在这里俯瞰什么?

0 个答案:

没有答案