我有一个模型,其中包含一个表“标签”的 ManyToMany 字段。由于这个表可能很大,我不想在表单中显示一个选择,而是一个逗号分隔的标签列表,由一个字符域提供(我想)。
在保存时,我会用逗号拆分列表,然后将它们一一添加(使用 get_or_create)。我已经这样做了。
但是当我想更改数据时,我有一个 ID 列表,而不是标签列表。
如何显示逗号分隔的标签列表?我是否必须为此创建一个新的特定字段?还是已经有一些东西可以做我正在寻找的东西?
谢谢你的帮助!
我有一个模型,其中包含一个表“标签”的 ManyToMany 字段。由于这个表可能很大,我不想在表单中显示一个选择,而是一个逗号分隔的标签列表,由一个字符域提供(我想)。
在保存时,我会用逗号拆分列表,然后将它们一一添加(使用 get_or_create)。我已经这样做了。
但是当我想更改数据时,我有一个 ID 列表,而不是标签列表。
如何显示逗号分隔的标签列表?我是否必须为此创建一个新的特定字段?还是已经有一些东西可以做我正在寻找的东西?
谢谢你的帮助!
您需要创建一个自定义小部件(我不知道有一个内置小部件可以完全满足您的需求)。最有用的例子可能是 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
上面的代码可以以更优化的方式使用查询,例如
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))