2

我有一个模型,其中包含一个表“标签”的 ManyToMany 字段。由于这个表可能很大,我不想在表单中显示一个选择,而是一个逗号分隔的标签列表,由一个字符域提供(我想)。

在保存时,我会用逗号拆分列表,然后将它们一一添加(使用 get_or_create)。我已经这样做了。

但是当我想更改数据时,我有一个 ID 列表,而不是标签列表。

如何显示逗号分隔的标签列表?我是否必须为此创建一个新的特定字段?还是已经有一些东西可以做我正在寻找的东西?

谢谢你的帮助!

4

2 回答 2

3

您需要创建一个自定义小部件(我不知道有一个内置小部件可以完全满足您的需求)。最有用的例子可能是 Django 附带的小部件(在 forms/widgets.py 中)。您还可以在此处查看创建自定义小部件的示例。

我做了一些摆弄,在调整了内置Input小部件之后,这就是我想出的;我做了一些测试,它对我有用:

class CommaTags(Widget):
    def render(self, name, value, attrs=None):
        final_attrs = self.build_attrs(attrs, type='text', name=name)
        objects = []
        for each in value:
            try:
                object = Tag.objects.get(pk=each)
            except:
                continue
            objects.append(object)

        values = []
        for each in objects:
            values.append(str(each))
        value = ', '.join(values)
        if value: # only add 'value' if it's nonempty
            final_attrs['value'] = force_unicode(value)
        return mark_safe(u'<input%s />' % flatatt(final_attrs))

请注意,在此示例中,小部件被硬编码为使用假设Tag模型,并且它只是使用str()每个对象的方法作为逗号分隔列表中显示的内容。您可能需要更改这些以适合您的使用。另外,我直接在forms/widgets.py 中有这个,所以如果你把它放在其他地方(就像你应该做的那样),你需要导入我使用的一些东西。

创建完成后,您可以在表单中将其指定为 ModelMultipleChoiceField 的小部件,如下所示:

from django import forms

class TagForm(forms.ModelForm):
    tags = forms.ModelMultipleChoiceField(queryset=Tag.objects.all(),
                                          widget=CommaTags)
    class Meta:
        model = Tag
于 2011-02-10T17:47:48.220 回答
0

上面的代码可以以更优化的方式使用查询,例如

class CommaTags(Widget):
    def render(self, name, value, attrs=None):
        value = Tag.objects.filter(pk__in=each) \
            .exclude(name__exact='') \
            .values_list("name") \
            .join(", ")

        if value:
            final_attrs['value'] = force_unicode(value)

        return mark_safe(u'<input%s />' % flatatt(final_attrs))
于 2019-08-06T11:07:16.943 回答