自定义Django字段以存储电子邮件地址列表

时间:2010-11-02 12:49:35

标签: python 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列表表示转换回字符串以便在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)

这取决于此处所述的SeparatedValuesFieldhttp://www.davidcramer.net/code/181/custom-fields-in-django.html

4 个答案:

答案 0 :(得分:3)

我不会这样做。我会将与EmailListField相关联的任何内容与电子邮件地址字段中的一对多联系起来。

答案 1 :(得分: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(',')])    

答案 2 :(得分: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())

答案 3 :(得分: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(',')])