IntegrityError: UNIQUE constraint failed: portal_academy.user_id

This error occurs when same user in the database try to save a data. i notice this error while i was working with modelform. I try to save directly from the database by picking the same User, but this erro occurs in the database ‘‘Academy with this User already exists.’’ below are my logics.

forms.py

  class academyForm(ModelForm):
      
      widgets= {
          'institution': forms.Select(choices=ACADEMY_CHOICES,
          attrs={
              "placeholder": "Institution Attended",
              "class": "form-control"
          })
      }
      widgets= {
          'certificate_obtained': forms.Select(choices=CERTIFICATE_CHOICES,
          attrs={
              "placeholder": "Certificate Obtained",
              "class": "form-control"
          })
      }
      
      date_obtained = forms.DateField(
          widget=forms.DateInput(
              attrs={
                  "placeholder": "Date obtained",
                  "class": "form-control",
                  "type":"date"
              }
          ))
  
      widgets= {
          'document': forms.FileInput(
          attrs={
              "placeholder": "Document",
              "class": "form-control"
          })
      }
  
      class Meta:
  
          model = Academy
          fields = ('institution', 'certificate_obtained', 'date_obtained', 'document')

views.py

  def academy(request):
      user=  User.objects.get(username= request.user)
      
      credential =Academy.objects.filter(user_id =user).order_by('user_id')
  
      if request.method == 'POST':
          
          form =academyForm(request.POST,  request.FILES)
          
          if form.is_valid():
              form.instance.user =request.user
              institution =form.cleaned_data.get('institution')
              certificate =form.cleaned_data.get('certificate_obtained')
              dates =form.cleaned_data.get('date_obtained')
              document =form.cleaned_data.get('document')
  
              # try:
              academy, created= Academy.objects.get_or_create(user=user, institution = institution, certificate_obtained=certificate, date_obtained =dates, document =document)
                  
              # except:
                  # messages.error(request, 'Cannot submit credential twice!')
                  # return redirect('academy')
  
          messages.success(request, 'User data saved successful! Click next to proceed')
          return redirect('academy')
          
      
      form = academyForm()
      
      return render(request, 'portal/home/credential.html', {'form':form, 'credentials':credential } )

this is the model.py

class Academy(models.Model):
    user =models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank = True)
    institution =models.CharField(choices=ACADEMY_CHOICES, max_length=100, null=True, blank = True)
        certificate_obtained=models.CharField(choices=CERTIFICATE_CHOICES, max_length=100, null=True, blank = True)
        date_obtained =models.DateField(null =True, blank=True)
        document = models.FileField(upload_to='document')
        # personalinfo =models.ForeignKey('Personalinfo', on_delete=models.CASCADE, null=True, blank = True)
        # job =models.ForeignKey('Job', on_delete=models.CASCADE, null=True, blank = True)

    def __str__(self):
        return self.certificate_obtained

Most likely, the issue here is this line.

(Note: In the future, please post the complete error messages being received and not just the single-line description. Frequently, there’s very useful information within that full traceback.)

This formulation of the get_or_create function is going to try to create a new instance if any one field of that set are different. You probably want to check for this instance earlier in your processing - perhaps even altering the binding of your form data to that existing instance when appropriate.

Since you’ve established a one-to-one relationship between Academy and User, you’re only going to have one instance of Academy for any User, so you can check the user object to see if the Academy exists, and handle it accordingly.

Side notes:

  • Your first query on user is unnecessary. The request.user is the User object you’re trying to get. There’s no need to query on it.

  • Your query for credential is unnecessary. Because of the one-to-one relationship, you have access to that instance as user.academy.

  • You don’t need to extract individual ModelForm fields from the form to assign them to variables to be set in the model. The form.save() method is all you need.

You might want to review the Working with forms docs docs along with the forms API.

1 Like

Thank you so much. The challenge is solved! I went through all your explanation and from this brief explanation you made, I gain a better understanding of relationship. My challenge occurs exactly at one-to-one relationship in the academy table with user. It is not relevant to what I need. I changed it to ForeignKey and I have the problem solved.

I will appreciate if you can have time and give me more explanation about relationship in your own way. And refer me to how I can gain better understanding of “Dynamic querryset”. Thanks much.