title: Django form with IntegrityError exception
body: <p>I would like to get your help in order to use <code>except IntegrityError</code> in my <code>formset</code>.</p>
  
  <p>I have my model file :</p>
  
  <pre><code>class Document(models.Model):
  
      code = models.CharField(max_length=25, verbose_name=_('code'), unique=True, null=False, blank=False, default='')
      language = models.CharField(max_length=2, verbose_name=_('language'), choices=LANGUAGE_CHOICES)
      format = models.CharField(max_length=10, verbose_name=_('format'), choices=FORMAT_CHOICES)
      title = models.CharField(max_length=512, verbose_name=_('title'))
      publication = models.ForeignKey(Publication, verbose_name=_('publication title'), related_name='documents')
      upload = models.FileField(upload_to='media/', validators=[validate_file_extension], verbose_name=_('document file'), )
  
      class Meta:
          verbose_name = _('document')
          verbose_name_plural = _('documents')
  
      def save(self, *args, **kwargs):
          self.code = f"{self.publication.pub_id}-{self.language.upper()}-{self.format.upper()}"
          super(Document, self).save(*args, **kwargs)
  
      def __str__(self):
          return f"{self.title}"
  </code></pre>
  
  <p>As you can see, the <code>code field</code> depends from data filled by user with the associated form.
  Each <code>code</code> field has to be unique.</p>
  
  <p>I have a formset :</p>
  
  <pre><code>class DocumentForm(forms.ModelForm):
  
      def __init__(self, *args, **kwargs):
          super(DocumentForm, self).__init__(*args, **kwargs)
  
          for key in self.fields:
              self.fields[key].required = True
  
      class Meta:
          model = Document
          fields = ['publication', 'language', 'format', 'title', 'upload']
  
  
  DocumentFormSet = inlineformset_factory(Publication, Document, form=DocumentForm, extra=1, max_num=4, can_delete=True)
  </code></pre>
  
  <p>And I have a views.py file with an <code>except IntegrityError</code> if user fills different form in formset with same value. Because it will create the same <code>code</code> ang user will get an error.</p>
  
  <pre><code>class PublicationCreateView(CreateView):
      model = Publication
      template_name = 'publication_form.html'
  
      def get_context_data(self, **kwargs):
          context = super(PublicationCreateView, self).get_context_data(**kwargs)
          document_queryset = Document.objects.all()
          context['DocumentFormSets'] = DocumentFormSet(self.request.POST or None, self.request.FILES or None,
                                                        prefix='doc', queryset=document_queryset)
          return context
  
      def form_valid(self, form):
          try:
              context = self.get_context_data()
              formsets = context['DocumentFormSets']
              if form.is_valid():
                  self.object = form.save()
                  if formsets.is_valid():
                      formsets.instance = self.object
                      formsets.save(commit=False)
                      for element in formsets:
                          element.save(commit=False)
                          formsets.save()
              return super(PublicationCreateView, self).form_valid(form)
          except IntegrityError:
              messages.error(self.request, _(f"Issue with documents"))
              return render(self.request, self.template_name)
  </code></pre>
  
  <p>You can find my template, but I don't know if it's necessary !</p>
  
  <pre><code>&lt;form method="post" action="" enctype="multipart/form-data" novalidate&gt;
        {% csrf_token %}
  {#      {{ form.management_form }}#}
  
        &lt;fieldset&gt;
          &lt;legend class="title"&gt;&lt;span class="name"&gt;{% trans 'Publication form' %}&lt;/span&gt;&lt;/legend&gt;
          &lt;div class="row"&gt;
            &lt;div class="col-xs-6"&gt;
              {{ form.category|as_crispy_field }}
            &lt;/div&gt;
            &lt;div class="col-xs-6"&gt;
              {{ form.pub_id|as_crispy_field }}
            &lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="row"&gt;
            &lt;div class="col-xs-6"&gt;
              {{ form.title|as_crispy_field }}
            &lt;/div&gt;
            &lt;div class="col-xs-6"&gt;
              {{ form.cover|as_crispy_field }}
            &lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="row"&gt;
            &lt;div class="col-xs-12"&gt;
              {{ form.description|as_crispy_field }}
            &lt;/div&gt;
          &lt;/div&gt;
        &lt;/fieldset&gt;
  
        &lt;fieldset&gt;
          &lt;legend class="title"&gt;&lt;span class="name"&gt;{% trans 'Document form' %}&lt;/span&gt;&lt;/legend&gt;
          {{ DocumentFormSets.management_form }}
          &lt;div id="form_set"&gt;
            {% for form in DocumentFormSets.forms %}
              &lt;div class='formset-document'&gt;
                &lt;table class='no_error'&gt;
                  &lt;div class="row"&gt;
                    &lt;div class="col-xs-3"&gt;
                      {{ form.title|as_crispy_field }}
                    &lt;/div&gt;
                    &lt;div class="col-xs-3"&gt;
                      {{ form.language|as_crispy_field }}
                    &lt;/div&gt;
                    &lt;div class="col-xs-3"&gt;
                      {{ form.format|as_crispy_field }}
                    &lt;/div&gt;
                    &lt;div class="col-xs-3"&gt;
                      {{ form.upload|as_crispy_field }}
                    &lt;/div&gt;
                  &lt;/div&gt;
                &lt;/table&gt;
              &lt;/div&gt;
            {% endfor %}
          &lt;/div&gt;
          &lt;br&gt;
          &lt;input type="button" class="btn btn-default" value="Add More" id="add_more"&gt;
          &lt;div id="empty_form" style="display:none"&gt;
            &lt;table class='no_error'&gt;
              &lt;div class="row"&gt;
                &lt;div class="col-xs-3"&gt;
                  {{ DocumentFormSets.empty_form.title|as_crispy_field }}
                &lt;/div&gt;
                &lt;div class="col-xs-3"&gt;
                  {{ DocumentFormSets.empty_form.language|as_crispy_field }}
                &lt;/div&gt;
                &lt;div class="col-xs-3"&gt;
                  {{ DocumentFormSets.empty_form.format|as_crispy_field }}
                &lt;/div&gt;
                &lt;div class="col-xs-3"&gt;
                  {{ DocumentFormSets.empty_form.upload|as_crispy_field }}
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/table&gt;
          &lt;/div&gt;
        &lt;/fieldset&gt;
  
        &lt;br&gt;
        &lt;input type="submit" class="btn btn-default" value="{% trans 'Save' %}"/&gt;
        &lt;a href="{{ request.META.HTTP_REFERER }}" class="btn btn-default"&gt;{% trans 'Cancel' %}&lt;/a&gt;
      &lt;/form&gt;
  </code></pre>
  
  <p>I get this issue :</p>
  
  <pre><code>Exception Value: |as_crispy_field got passed an invalid or inexistent field
  </code></pre>
  
  <p>Because :</p>
  
  <blockquote>
    <p>The above exception (duplicate key value violates unique constraint
    "freepub_document_code_key" DETAIL: Key (code)=(PUBSD-8119-FR-PDF)
    already exists. ) was the direct cause of the following exception:
    formsets.save()</p>
  </blockquote>
  
  <p><strong>EDIT :</strong></p>
  
  <p>I tried :</p>
  
  <pre><code>try:
      context = self.get_context_data()
      formsets = context['DocumentFormSets']
      if form.is_valid():
          self.object = form.save()
          if formsets.is_valid():
              formsets.instance = self.object
              formsets.save(commit=False)
              for element in formsets:
                  element.save(commit=False)
                  formsets.save()
      return super(PublicationCreateView, self).form_valid(form)
  except IntegrityError:
      messages.error(self.request, _(f"Issue with documents"))
      return super(PublicationCreateView, self).form_invalid(form)
  </code></pre>
  
  <p>I seems to work, but maybe I don't have to same my first form because he has unique value too and if I change value according to form_invalid(), I have to change this one too.</p>