django-multi-email-field
django-multi-email-field version 0.8.0 provides a reusable model field and a form field for Django to manage lists of email addresses. It stores multiple emails as a single comma-separated string in the database and provides appropriate validation and a dedicated widget for forms. Releases are infrequent but stable, primarily for Django compatibility updates.
Common errors
-
ModuleNotFoundError: No module named 'multi_email_field'
cause The `django-multi-email-field` package is not installed or the import path is incorrect.fixEnsure the package is installed with `pip install django-multi-email-field`. Double-check import statements like `from multi_email_field.fields import MultiEmailField`. -
AttributeError: 'MultiEmailField' object has no attribute 'clean'
cause This usually occurs when attempting to use the `MultiEmailField` from `multi_email_field.fields` (designed for models) directly as a form field, or vice-versa, without proper Django form integration.fixWhen defining forms, explicitly import and use `MultiEmailField` from `multi_email_field.forms`. If using a `ModelForm`, ensure the model field type is correctly mapped or overridden by the form field type. -
django.db.utils.DataError: value too long for type character varying(255)
cause You have provided a combined string of email addresses (including commas) that exceeds the `max_length` defined for the `MultiEmailField` in your model.fixIncrease the `max_length` argument of your `ModelMultiEmailField` in `models.py` to accommodate longer email lists, then run `makemigrations` and `migrate`. -
ValidationError: ['Enter a valid email address.']
cause One or more email addresses in the input string are syntactically invalid according to Django's email validator.fixCheck the input string for typos, missing '@' symbols, invalid domains, or other format errors. Each email address must pass standard email validation.
Warnings
- gotcha The `MultiEmailField` stores all email addresses as a single comma-separated string in the database, not as a list or JSON array. When retrieving directly from the database or performing raw queries, remember to parse this string.
- gotcha The `max_length` argument on `MultiEmailField` applies to the *entire* comma-separated string, including commas. It does not limit the length of individual email addresses.
- gotcha The `MultiEmailField` name is used for both the model field (`multi_email_field.fields.MultiEmailField`) and the form field (`multi_email_field.forms.MultiEmailField`). Confusing their import paths will lead to `AttributeError` or unexpected behavior.
- gotcha If any email address in the input string is invalid, the field will fail validation and return a generic `ValidationError: ['Enter a valid email address.']` for the entire field, without specifying which email was problematic.
Install
-
pip install django-multi-email-field
Imports
- MultiEmailField
from multi_email_field.forms import MultiEmailField # For model fields
from multi_email_field.fields import MultiEmailField
- MultiEmailField
from multi_email_field.fields import MultiEmailField # For form fields
from multi_email_field.forms import MultiEmailField
- MultiEmailWidget
from multi_email_field.widgets import MultiEmailWidget
Quickstart
import os
from django.conf import settings
from django.db import models
from django import forms
from multi_email_field.fields import MultiEmailField as ModelMultiEmailField
from multi_email_field.forms import MultiEmailField as FormMultiEmailField
from multi_email_field.widgets import MultiEmailWidget
# Minimal Django setup (required for models/forms to be defined outside a full project)
if not settings.configured:
settings.configure(
INSTALLED_APPS=[
'django.contrib.auth',
'django.contrib.contenttypes',
'my_app', # A dummy app for model registration
],
DATABASES={'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}},
DEBUG=True,
)
# Required for Django apps to be ready for model creation
import django
django.setup()
# Define a placeholder app to allow models to be registered
class MyAppConfig(object):
name = 'my_app'
label = 'my_app'
# Example Model integrating MultiEmailField
class Contact(models.Model):
name = models.CharField(max_length=100)
emails = ModelMultiEmailField(blank=True, default='')
def __str__(self):
return self.name
# Example Form using MultiEmailField and its widget
class ContactForm(forms.ModelForm):
emails = FormMultiEmailField(
widget=MultiEmailWidget(attrs={'rows': 3, 'placeholder': 'email1@example.com, email2@test.org'})
)
class Meta:
model = Contact
fields = ['name', 'emails']
# Example usage (uncomment to run in a script):
# from django.core.exceptions import ValidationError
# try:
# contact_instance = Contact.objects.create(name="Jane Doe", emails="jane@example.com, jane2@test.org")
# print(f"Created contact: {contact_instance.name} with emails: {contact_instance.emails}")
# form = ContactForm(instance=contact_instance)
# print("\n--- ContactForm (edit existing) ---")
# print(form.as_p()) # Render the form fields
# form_data = {'name': 'New User', 'emails': 'user@example.com, another@domain.com'}
# new_form = ContactForm(form_data)
# if new_form.is_valid():
# print("\n--- New ContactForm (valid) ---")
# new_contact = new_form.save()
# print(f"Saved new contact: {new_contact.name} with emails: {new_contact.emails}")
# else:
# print("New form errors:", new_form.errors)
# invalid_form_data = {'name': 'Bad User', 'emails': 'invalid-email, user@domain.com'}
# invalid_form = ContactForm(invalid_form_data)
# if not invalid_form.is_valid():
# print("\n--- Invalid ContactForm (expected errors) ---")
# print("Invalid form errors:", invalid_form.errors)
# except Exception as e:
# print(f"An error occurred during example usage: {e}")