title: "This field cannot be null" error in a django 1.5 ModelForm
body: <p>I managed to create a ModelForm that basically insert an Alert object in DB linked to an Application on an Environment that will send mail to a Contact (managed with ForeignKey). My form (based on a CreateView class-based form) is composed of 3 fields:</p>
  
  <ul>
  <li>a CharField for the application</li>
  <li>a ModelChoiceField for the environment </li>
  <li>an EmailField for the contact</li>
  </ul>
  
  <p>The CreateView is mixed-in with some AJAX logic to make the submit thing overall dynamic (i.e. drawing tooltips for errors without reloading the page next to each field instead of having a big error  above the form).</p>
  
  <p>The logic of the ModelForm is to:</p>
  
  <ol>
  <li>Check if the application already exists in DB. Otherwise it raises a ValidationError</li>
  <li>Check if the contact mail address exists in DB. Otherwise it creates it</li>
  <li>Check if the resulting Alert object to create already exists in DB. If it exists it raises a ValidationError.</li>
  </ol>
  
  <p>Everything works fine so far except when I want to submit my form with a non existing contact mail address, the ModelForm raises an "This field cannot be null" validation error.</p>
  
  <p>I really didn't find what I'm doing wrong since I use get_or_create() method in clean_contact() method of my ModelForm to insert this contact if needed then return the resulting object to update self.cleaned_data dictionary. Worst thing is that when I submit a second time the form without changing any field everything runs smooth (no more validation error)...</p>
  
  <p>When I submit the form with an existing mail address in database everything is working fine at the first form submit.</p>
  
  <p>I'd really appreciate if you guys can help to point out what is wrong in my code and why this error is raised whereas every POSTed data is correct.</p>
  
  <p>However I've a little doubt about the AJAX mixin with my CreateView since maybe it could be that when a mail address is not known, get_or_create() create and returns it but - I can't imagine why - the creation of the Alert object could not yet reference the newly created Contact object. This could explain why a second submit works... I'm sure you guys will get the final word on this :-)</p>
  
  <p>Below different application parts involved in the aforementioned issue. I voluntarily removed some Model fields that are not used for this application as well as LoginRequiredMixin inherited from my CreateView.</p>
  
  <p>Again I'd really appreciate your help on that and thank you in advance for every piece of advice.</p>
  
  <h1>Models</h1>
  
  <pre class="lang-py prettyprint-override"><code>class UmsAlerting(models.Model):
      alert_id = models.IntegerField(primary_key=True, editable=False)
      appli = models.ForeignKey('UmsApplication')
      env = models.ForeignKey('UmsEnvironment')
      contact = models.ForeignKey('UmsContacts')
      class Meta:
          db_table = 'ums_alerting'
      def __unicode__(self):
          return u'Alert_Id %d on %s(%s)' %(self.alert_id, self.appli.trigram_ums, self.env.env_name)
  
  
  class UmsApplication(models.Model):
      appli_id = models.IntegerField(primary_key=True)
      trigram_ums = models.CharField(max_length=4L)
      class Meta:
          db_table = 'ums_application'
  
  
  class UmsContacts(models.Model):
      contact_id = models.IntegerField(primary_key=True)
      mail_addr = models.CharField(max_length=100L)
      class Meta:
          db_table = 'ums_contacts'
  
  
  class UmsEnvironment(models.Model):
      env_id = models.IntegerField(primary_key=True)
      env_name = models.CharField(max_length=5L)
      class Meta:
          db_table = 'ums_environment'
  
      def __unicode__(self):
          return self.env_name
  </code></pre>
  
  <h1>ModelForm</h1>
  
  <pre class="lang-py prettyprint-override"><code>class AlertForm(ModelForm):
      class Meta:
          model = UmsAlerting
          exclude = ('custom_rule')
  
      appli = forms.CharField(required=True, max_length=3)
      env = forms.ModelChoiceField(required=True,
                                   queryset=UmsEnvironment.objects.all())
      contact = forms.EmailField(required=True)
  
      def clean_appli(self):
          data = self.cleaned_data['appli']
  
          try:
              UmsApplication.objects.get(trigram_ums=data)
          except ObjectDoesNotExist:
              msg = 'Trigram must be known and valid.'
              self._errors['appli'] = self.error_class([msg])
              raise forms.ValidationError(msg)
  
          return UmsApplication.objects.get(trigram_ums=data)
  
      def clean_contact(self):
          data = self.cleaned_data['contact']
          c, created = UmsContacts.objects.get_or_create(mail_addr=data)
  
          return c
  
  
      def clean(self):
          cleaned_data = super(AlertForm, self).clean()
          app = cleaned_data.get('appli')
          contact = cleaned_data.get('contact')
          env = cleaned_data.get('env')
  
          # Do not insert a new alert if it already exists
          if UmsAlerting.objects.filter(appli=app, env=env, contact=contact).count() &gt; 0:
              msg = 'Alert is already configured.'
              self._errors['contact'] = self.error_class([msg])
              raise forms.ValidationError(msg)
  
          # Return the parent's clean method finally
          return cleaned_data
  </code></pre>
  
  <h1>CreateView</h1>
  
  <pre class="lang-py prettyprint-override"><code>class AlertView(LoginRequiredMixin, AjaxResponseMixin, CreateView):
       template_name = 'tools/alert_form.html'
       form_class = AlertForm
       success_url = reverse_lazy('alerts_configure')
  </code></pre>
  
  <h1>AjaxResponseMixin</h1>
  
  <pre class="lang-py prettyprint-override"><code>class AjaxResponseMixin(object):
       def render_to_json_response(self, context, **kwargs):
           data = json.dumps(context)
           kwargs['content_type'] = 'application/json'
           return HttpResponse(data, **kwargs)
  
       def form_invalid(self, form):
           response = super(AjaxResponseMixin, self).form_invalid(form)
           if self.request.is_ajax():
               return self.render_to_json_response(form.errors, status=400)
           else:
               return response
  
       # Not really useful actually (yet)
       def form_valid(self, form):
           response = super(AjaxResponseMixin, self).form_valid(form)
           if self.request.is_ajax():
               return self.render_to_json_response(json.dumps({}))
           else:
               return response
  </code></pre>