How to change the value of custom model field displayed in django admin

1.3k Views Asked by At

I have this code:

import re
import six

from django.core.validators import validate_email
from django.db.models import TextField, SubfieldBase


class EmailsListField(TextField):
    __metaclass__ = SubfieldBase
    email_separator_re = re.compile(r'\s*,\s*')

    def to_python(self, value):
        if isinstance(value, six.string_types):
            return [x for x in self.email_separator_re.split(value) if x]
        else:
            return list(value)

    def validate(self, value, model_instance):
        super(EmailsListField, self).validate(value, model_instance)

        for email in value:
            validate_email(email)

    def get_prep_value(self, value):
        if isinstance(value, six.string_types):
            return value
        else:
            return ', '.join(value)

It is designed to accept many emails from a text box, validate, and store them. It saves them as text (e.g. "[email protected], [email protected]") in the db. Everything works as expected except in the admin textboxes and in the list view (and presumably elsewhere). The values are displayed as u"['[email protected]', '[email protected]']". This is, of course, an invalid format as well as ugly.

How do I change this so that it displays as '[email protected], [email protected]' in both the textboxes and list view?

1

There are 1 best solutions below

0
On

Thanks to @arocks and @eviltnan.

This answer works for me: https://stackoverflow.com/a/20545049/1813277. In short, a custom list subclass is used with overwritten __str__ functions.

This is my end solution:

import re
import six

from django.core.validators import validate_email
from django.db.models import TextField, SubfieldBase


class EmailsListField(TextField):
    __metaclass__ = SubfieldBase
    email_separator_re = re.compile(r'\s*,\s*')

    class AdminList(list):
        def __str__(self):
            return str(', '.join(self))

        def __unicode__(self):
            return unicode(', '.join(self))

    def to_python(self, value):
        if isinstance(value, six.string_types):
            return self.AdminList([x for x in self.email_separator_re.split(value) if x])
        else:
            return self.AdminList(value)

    def validate(self, value, model_instance):
        super(EmailsListField, self).validate(value, model_instance)

        for email in value:
            validate_email(email)

    def get_prep_value(self, value):
        if isinstance(value, six.string_types):
            return value
        else:
            return ', '.join(value)