Пользовательское поле Django для хранения списка адресов электронной почты

Я пытаюсь добавить в модель Django поле, которое будет представлять список адресов электронной почты. Я хотел бы, чтобы пользователь вводил список адресов через запятую в форму в администраторе, которую мое приложение затем будет анализировать для отправки серии электронных писем.

Моя текущая реализация охватывает основную идею, но имеет существенное ограничение. В админке, если я введу строку вроде foo@example.com, bar@example.comзатем корректно записывает это в базу данных как [u'foo@example.com', u'bar@example.com'], Но администратор отображает это сериализованное значение вместо гуманизированной строки. Что еще более важно, если я редактирую и сохраняю запись, без внесения каких-либо изменений, то же преобразование изменяется [u'foo@example.com', u'bar@example.com'] в [u"[u'foo@example.com'", u"u'bar@example.com']"],

Как мне преобразовать представление списка Python обратно в строку для использования в админке? Это цель value_to_string метод или мне нужно сделать преобразование в другом месте?

Мое текущее поле настраиваемой модели выглядит следующим образом:

class EmailListField(models.TextField):
    __metaclass__ = models.SubfieldBase

    def to_python(self, value):
        if not value:
            return
        if isinstance(value, list):
            return value
        return [address.strip() for address in value.split(',')]

    def get_db_prep_value(self, value):
        if not value:
            return
        return ','.join(unicode(s) for s in value)

    def value_to_string(self, obj):
        value = self._get_val_from_obj(obj)
        return self.get_db_prep_value(value)

Это основано на SeparatedValuesField описано здесь: http://www.davidcramer.net/code/181/custom-fields-in-django.html.

4 ответа

Решение

Я бы не стал этого делать. Я бы сделал все, что вы EmailListField должен быть связан с полями адреса электронной почты "один-ко-многим".

Я основал это на документации, но вместо этого это модельное поле:

class MultiEmailField(models.TextField):

    def to_python(self, value):

        if not value:
            return None  # []

        cleaned_email_list = list()
        #email_list = filter(None, value.split(','))
        email_list = filter(None, re.split(r';|,\s|\n', value))

        for email in email_list:
            if email.strip(' @;,'):
                cleaned_email_list.append(email.strip(' @;,'))

        print cleaned_email_list
        cleaned_email_list = list(set(cleaned_email_list))

        return ", ".join(cleaned_email_list)

    def validate(self, value, model_instance):
        """Check if value consists only of valid emails."""

        # Use the parent's handling of required fields, etc.
        super(MultiEmailField, self).validate(value, model_instance)

        email_list = value.split(',')

        for email in email_list:
            validate_email(email.strip())

Вопрос мертв, но вы можете сделать это, добавив конкретную презентацию в ваш python val

class EmailDomainsListField(models.TextField):
    __metaclass__ = models.SubfieldBase

    class Presentation(list):

        def __unicode__(self):
            return u",".join(self)
        def __str__(self):
            return ",".join(self)
    ...

    def to_python(self, value):
        if not value:
            return
        if isinstance(value, EmailDomainsListField.Presentation):
            return value
        return EmailDomainsListField.Presentation([address.strip() for address in        value.split(',')])    

Ниже приведено поле модели с проверкой каждого электронного письма и правильной обработкой администратором. Основано на eviltnan и AndrewF ответах.

from django.core import validators
from django.db import models


class EmailListField(models.CharField):
    __metaclass__ = models.SubfieldBase

    class EmailListValidator(validators.EmailValidator):
        def __call__(self, value):
            for email in value:
                super(EmailListField.EmailListValidator, self).__call__(email)

    class Presentation(list):

        def __unicode__(self):
            return u", ".join(self)

        def __str__(self):
            return ", ".join(self)

    default_validators = [EmailListValidator()]

    def get_db_prep_value(self, value, *args, **kwargs):
        if not value:
            return
        return ','.join(unicode(s) for s in value)

    def value_to_string(self, obj):
        value = self._get_val_from_obj(obj)
        return self.get_db_prep_value(value)

    def to_python(self, value):
        if not value:
            return
        if isinstance(value, self.Presentation):
            return value
        return self.Presentation([address.strip() for address in value.split(',')])
Другие вопросы по тегам