Django管理界面将字符u“[]添加到具有SeparatedValuesField的字符串列表中

时间:2011-12-19 21:59:36

标签: python django csv django-admin

我正在使用SeparatedValuesField来跟踪字符串列表,如http://davidcramer.posterous.com/code/181/custom-fields-in-django.html所述,以及SO上的很多帖子都建议将其作为存储字符串列表的正确方法。

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    device_ids = SeparatedValuesField(blank=True, null=True, default=[])

它在我的应用程序中工作正常,我可以添加设备ID并在管理界面中按预期查看它们。

user_profile.device_ids = ['666666-D849-524F-6984-7E9B2D768546']

但问题在于管理界面,当我打开UserProfile对象的详细信息页面时,管理界面本身正在为我的device_ids字段添加额外的值。

例如,我的应用程序在字段中插入一个值,当我在管理界面中查看它时,它看起来像这样:

[u'666666-D849-524F-6984-7E9B2D768546']

然后我在我的UserProfile对象上更改了一些其他随机属性,并使用内置的django管理界面保存按钮保存它。

当我再次为我的对象打开UserProfile对象详细信息页面时,该值现在如下所示:

[u"[u'666666-D849-524F-6984-7E9B2D768546']"]

如果我重复这个只是点击保存然后打开这个详细页面的过程,它将继续用u“[]字符嵌套实际值。

我可以做些什么来改变这个功能吗?我应该以不同的方式存储字符串列表吗?

2 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,最后由于这两个different answers而想出来了。

在这种情况下,您需要的是一个自定义窗口小部件,它将字符串列表呈现为字符串。此小部件需要绑定到自定义字段:

class FlattenListWidget(forms.TextInput):
    def render(self, name, value, attrs=None):
        if not value is None:
            value = ','.join(str(v) for v in value)
        return super(FlattenListWidget, self).render(name, value, attrs)

class UserProfileAdminForm(forms.ModelForm):
    class Meta:
        model = UserModel
        widgets = {
            'device_ids': FlattenListWidget(),
        }

class UserProfileAdmin(admin.ModelAdmin):
    form = UserProfileAdminForm

希望有效。我的代码中有不同的模型名称,但设法从我的自定义字段中获取包含逗号分隔值列表的文本输入。

如果您想使用逗号空格value = ', '.join(str(v) for v in value)加入字符串,请记住strip()自定义字段get_db_prep_value方法中的值。否则,空格将被保存回数据库。

要使用list_display中的自定义字段,您可以向管理模型添加自定义字段:

class UserProfileAdmin(admin.ModelAdmin):
    form = UserProfileAdminForm

    list_display = ('ids_list',)
    def ids_list(self, obj):
        if obj.device_ids:
            return ', '.join(str(i) for i in obj.device_ids)
        return None

答案 1 :(得分:1)

Oiva Eskola的答案看起来很好(尽管没有试过)。

在这个问题之前找到Django源代码,我也偶然发现了以下内容(有效):

SeparatedValuesField(models.TextField):
    # ...

    def value_from_object(self, obj):
        return self.get_db_prep_value(super(SeparatedValuesField, self).value_from_object(obj))