2010-11-02 3 views
8

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

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

Как преобразовать представление списка python обратно в строку для использования в admin? Это цель метода 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.

+0

это должен быть список будет что-то вроде запятую в примере DOCS - http://docs.djangoproject.com/en/dev/ref/forms/validation/#form-field- работа по очистке по умолчанию? – JamesO

+0

Спасибо, но этот пример предназначен для поля формы, чтобы проверить ввод пользователя. Мне нужно поле модели, чтобы сохранить несколько адресов в базе данных. – AndrewF

ответ

3

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

+0

Я вижу, как это более прямолинейно, но эти адреса электронной почты на самом деле не связаны ни с какими другими частями данных в моем приложении. Имеет ли смысл вводить новую таблицу email_address в базу данных, чтобы удерживать один столбец? – AndrewF

+1

Да, это лучший способ. Это также поможет другим способом, например, поиск и т. Д. – zsquare

+1

Обязательно соглашайтесь с zsquare. Это разумный способ сделать это. Вы также можете посмотреть на обработчик admin.TabularInline django, чтобы ваше приложение-администратор отображало список сообщений электронной почты «в строке» с объектом «Профиль» (или каким бы то ни было, с которым вы хотите связать EmailListField с). –

3

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

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(',')])  
1

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

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()) 
1

Ниже приведено поле модели с проверкой каждого письма и правильной обработкой администратора. На основе ответов 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(',')]) 
Смежные вопросы