2010-11-02 55 views
8

我想添加一個字段到一個Django模型,它將代表一個電子郵件地址列表。我希望用戶在管理員中輸入一個以逗號分隔的地址列表,然後我的應用程序會解析併發送一系列電子郵件。自定義Django字段來存儲電子郵件地址列表

我目前的實施涵蓋了基本思想,但有一個重大的侷限性。在管理員中,如果我輸入一個字符串,如[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列表表示重新轉換爲用於管理員的字符串?這是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) 

這是基於這裏所描述的SeparatedValuesFieldhttp://www.davidcramer.net/code/181/custom-fields-in-django.html

+0

它需要一個名單將像逗號的文檔例如分隔的列表 - http://docs.djangoproject.com/en/dev/ref/forms/validation/#form-field-默認清潔工作? – JamesO 2010-11-02 13:36:37

+0

謝謝,但這個例子是爲了表單域來驗證用戶的輸入。我需要的是一個模型字段,用於將多個地址保存到數據庫中。 – AndrewF 2010-11-02 14:07:29

回答

3

我不會那樣做。我會讓你的EmailListField應該與電子郵件地址字段的一對多關聯。

+0

我明白這是如何更直接,但這些電子郵件地址實際上並未與我的應用中的任何其他數據片段相關聯。將一個新的email_address表引入數據庫是否有意義,只需保存一列? – AndrewF 2010-11-02 16:13:43

+1

是的,這是更好的方法。這也將有助於其他方式,如搜索等。 – zsquare 2010-11-02 17:48:50

+1

必須與zsquare同意。這是明智的做法。您可能還想看看django的admin.TabularInline處理程序,以便您的管理應用程序可以使用Profile對象(或您希望與EmailListField關聯的任何內容)「在線」顯示電子郵件列表。 – 2010-11-02 21:20:32

3

問題是死的,但你可以通過添加特定的呈現給你的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(',')])  
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(',')]) 
相關問題