{"id":9677,"library":"django-multi-email-field","title":"django-multi-email-field","description":"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.","status":"active","version":"0.8.0","language":"en","source_language":"en","source_url":"https://github.com/mlewand/django-multi-email-field","tags":["django","email","forms","models","field","widget"],"install":[{"cmd":"pip install django-multi-email-field","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"This is a Django package, requiring Django>=3.2.","package":"Django","optional":false}],"imports":[{"note":"This is the model field. Do not use the form's MultiEmailField for models.","wrong":"from multi_email_field.forms import MultiEmailField # For model fields","symbol":"MultiEmailField","correct":"from multi_email_field.fields import MultiEmailField"},{"note":"This is the form field. Do not use the model's MultiEmailField for forms.","wrong":"from multi_email_field.fields import MultiEmailField # For form fields","symbol":"MultiEmailField","correct":"from multi_email_field.forms import MultiEmailField"},{"symbol":"MultiEmailWidget","correct":"from multi_email_field.widgets import MultiEmailWidget"}],"quickstart":{"code":"import os\nfrom django.conf import settings\nfrom django.db import models\nfrom django import forms\nfrom multi_email_field.fields import MultiEmailField as ModelMultiEmailField\nfrom multi_email_field.forms import MultiEmailField as FormMultiEmailField\nfrom multi_email_field.widgets import MultiEmailWidget\n\n# Minimal Django setup (required for models/forms to be defined outside a full project)\nif not settings.configured:\n    settings.configure(\n        INSTALLED_APPS=[\n            'django.contrib.auth',\n            'django.contrib.contenttypes',\n            'my_app', # A dummy app for model registration\n        ],\n        DATABASES={'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}},\n        DEBUG=True,\n    )\n    # Required for Django apps to be ready for model creation\n    import django\n    django.setup()\n\n# Define a placeholder app to allow models to be registered\nclass MyAppConfig(object):\n    name = 'my_app'\n    label = 'my_app'\n\n# Example Model integrating MultiEmailField\nclass Contact(models.Model):\n    name = models.CharField(max_length=100)\n    emails = ModelMultiEmailField(blank=True, default='')\n\n    def __str__(self):\n        return self.name\n\n# Example Form using MultiEmailField and its widget\nclass ContactForm(forms.ModelForm):\n    emails = FormMultiEmailField(\n        widget=MultiEmailWidget(attrs={'rows': 3, 'placeholder': 'email1@example.com, email2@test.org'})\n    )\n\n    class Meta:\n        model = Contact\n        fields = ['name', 'emails']\n\n# Example usage (uncomment to run in a script):\n# from django.core.exceptions import ValidationError\n# try:\n#     contact_instance = Contact.objects.create(name=\"Jane Doe\", emails=\"jane@example.com, jane2@test.org\")\n#     print(f\"Created contact: {contact_instance.name} with emails: {contact_instance.emails}\")\n#     form = ContactForm(instance=contact_instance)\n#     print(\"\\n--- ContactForm (edit existing) ---\")\n#     print(form.as_p()) # Render the form fields\n\n#     form_data = {'name': 'New User', 'emails': 'user@example.com, another@domain.com'}\n#     new_form = ContactForm(form_data)\n#     if new_form.is_valid():\n#         print(\"\\n--- New ContactForm (valid) ---\")\n#         new_contact = new_form.save()\n#         print(f\"Saved new contact: {new_contact.name} with emails: {new_contact.emails}\")\n#     else:\n#         print(\"New form errors:\", new_form.errors)\n\n#     invalid_form_data = {'name': 'Bad User', 'emails': 'invalid-email, user@domain.com'}\n#     invalid_form = ContactForm(invalid_form_data)\n#     if not invalid_form.is_valid():\n#         print(\"\\n--- Invalid ContactForm (expected errors) ---\")\n#         print(\"Invalid form errors:\", invalid_form.errors)\n# except Exception as e:\n#     print(f\"An error occurred during example usage: {e}\")\n","lang":"python","description":"Defines a Django model (`Contact`) using `ModelMultiEmailField` and a Django form (`ContactForm`) that utilizes `FormMultiEmailField` with `MultiEmailWidget` for managing multiple email addresses. Includes the minimal Django setup required for standalone execution."},"warnings":[{"fix":"If you need structured data (e.g., a Python list of emails) after retrieval, manually split the string: `emails_list = instance.emails.split(',')`.","message":"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.","severity":"gotcha","affected_versions":"0.1.0-0.8.0"},{"fix":"Carefully calculate the maximum combined length of all emails and separators you expect. If you exceed it, a `DataError` (PostgreSQL) or `IntegrityError` (MySQL) will be raised.","message":"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.","severity":"gotcha","affected_versions":"0.1.0-0.8.0"},{"fix":"Always use `from multi_email_field.fields import MultiEmailField` for model definitions and `from multi_email_field.forms import MultiEmailField` for form definitions. Using aliases like `ModelMultiEmailField` and `FormMultiEmailField` (as in the quickstart) can prevent clashes.","message":"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.","severity":"gotcha","affected_versions":"0.1.0-0.8.0"},{"fix":"Provide clear user-facing guidance on input format and consider custom JavaScript validation for immediate feedback on individual emails if a highly granular error message is critical for your UI.","message":"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.","severity":"gotcha","affected_versions":"0.1.0-0.8.0"}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"Ensure the package is installed with `pip install django-multi-email-field`. Double-check import statements like `from multi_email_field.fields import MultiEmailField`.","cause":"The `django-multi-email-field` package is not installed or the import path is incorrect.","error":"ModuleNotFoundError: No module named 'multi_email_field'"},{"fix":"When 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.","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.","error":"AttributeError: 'MultiEmailField' object has no attribute 'clean'"},{"fix":"Increase the `max_length` argument of your `ModelMultiEmailField` in `models.py` to accommodate longer email lists, then run `makemigrations` and `migrate`.","cause":"You have provided a combined string of email addresses (including commas) that exceeds the `max_length` defined for the `MultiEmailField` in your model.","error":"django.db.utils.DataError: value too long for type character varying(255)"},{"fix":"Check the input string for typos, missing '@' symbols, invalid domains, or other format errors. Each email address must pass standard email validation.","cause":"One or more email addresses in the input string are syntactically invalid according to Django's email validator.","error":"ValidationError: ['Enter a valid email address.']"}]}