I'm trying to add a field to a Django model that will represent a list of email addresses. I would like a user to enter a comma separated list of addresses into a form in the admin, which my app will then parse to send out a series of emails.
My current implementation covers the basic idea, but has a significant limitation. In the admin, if I enter a string like [email protected], [email protected]
, then it correctly writes this to the database as [u'[email protected]', u'[email protected]']
. But the admin displays this serialized value instead of the humanized string. More importantly, if I edit and save the record, without making any changes, the same conversion changes [u'[email protected]', u'[email protected]']
to [u"[u'[email protected]'", u"u'[email protected]']"]
.
How do I convert the python list representation back to a string for use in the admin? Is that the purpose of the value_to_string
method or do I need to make the conversion someplace else?
My current custom model field is as follows:
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)
This is based on the SeparatedValuesField
described here: http://www.davidcramer.net/code/181/custom-fields-in-django.html.
I based this off the docs but its a model field instead:
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())
I wouldn't do that. I would make whatever your EmailListField
is supposed to be associated with be one-to-many with email address fields.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With