David542
David542

Reputation: 110083

Possible to do with django forms?

I have a form where an administrators enters a list of comma-separated email addresses, and the form does validation on each email address before adding it to the db. I was able to do this just fine with using my own (non-django) form. I tried to migrate this over to using modelforms, but ran into a few problems. Here is the code I currently have --

# model
class EmailList(models.Model):
    email = models.EmailField(blank=True)
    network = models.ForeignKey(Network)

class EmailListForm(ModelForm):
    class Meta:
        model = EmailList

    def clean_email(self):
      if self.cleaned_data['email']:
          valid_emails = []
          for x in self.cleaned_data['email'].split(','):
              x = x.strip().lower()
              valid_emails.append(x)
          return valid_emails

# in views
def email(request):
    if request.POST.get('email'):
        for email in form.cleaned_data.get('email'):  ### ??
            if form.is_valid():                       ### ??
                EmailList.objects.create(email = email, network=Network.objects.get(id=request.POST['network']))
        return redirect('.')

I am having trouble because I can't call on the cleaned_data() until the form is validated, but the form will not validate as a whole (only its iterations will). Is it possible to construct this function using django's forms? If so, how would I accomplish this task? Thank you.

Upvotes: 1

Views: 263

Answers (1)

Maccesch
Maccesch

Reputation: 2128

In this case I wouldn't use a ModelForm because they are for the case that you want to represent one Model instance by one Form. Here you want to produce multiple instances with one form. So just write a common form with a custom field (there is acutally an example just for this in the Django docs) and maybe a custom save method:

from django import forms
from django.core.validators import validate_email

class MultiEmailField(forms.Field):
    def to_python(self, value):
        "Normalize data to a list of strings."

        # Return an empty list if no input was given.
        if not value:
            return []
        return value.split(',')

    def validate(self, value):
        "Check if value consists only of valid emails."

        # Use the parent's handling of required fields, etc.
        super(MultiEmailField, self).validate(value)

        for email in value:
            validate_email(email)


class EmailListForm(forms.Form):
    emails = forms.MulitEmailField()
    network = forms.ModelChoiceField(queryset=Network.objects.all())

    # save the emails to the db
    def save(self):
        for email in self.cleaned_data.get('emails'):
            EmailList.objects.create(email = email,
                                     network=self.network)

# in views
def email(request):
    if request.method == 'POST':
        form = EmailListForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect(...somewhere...)
    else:
        form = EmailListForm()

    return render(request, 'some/template.html', { 'form': form }

Upvotes: 2

Related Questions