i get an Integrity error when i try updating user information.

i am working with on a portfolio creating project which helps creates a simple portfolio for a user when they input information in a form. The information is gotten using AJAX. When a user first signs up and inputs information, the everything runs smoothly. But when a user tries to update information it triggers the error below. I have been trying to post this with the other code necessary but ‘Akismet’ keeps hiding my post and i don’t know what i am doing wrong.

Here i am trying to include the trace back in the comments if that would make a difference.

            Traceback (most recent call last):
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/db/backends/utils.py", line 86, in _execute
                return self.cursor.execute(sql, params)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/db/backends/sqlite3/base.py", line 396, in execute
                return Database.Cursor.execute(self, query, params)
            sqlite3.IntegrityError: UNIQUE constraint failed: portfolio_person.user_id

            The above exception was the direct cause of the following exception:

            Traceback (most recent call last):
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
                response = get_response(request)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/core/handlers/base.py", line 115, in _get_response
                response = self.process_exception_by_middleware(e, request)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response
                response = wrapped_callback(request, *callback_args, **callback_kwargs)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
                return view_func(request, *args, **kwargs)
            File "/home/jojoe/porfolio_app/portfolioapp/portfolio/views.py", line 17, in portfolio_form
                person.save()
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/db/models/base.py", line 745, in save
                self.save_base(using=using, force_insert=force_insert,
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/db/models/base.py", line 782, in save_base
                updated = self._save_table(
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/db/models/base.py", line 887, in _save_table
                results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/db/models/base.py", line 924, in _do_insert
                return manager._insert(
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/db/models/manager.py", line 82, in manager_method
                return getattr(self.get_queryset(), name)(*args, **kwargs)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/db/models/query.py", line 1204, in _insert
                return query.get_compiler(using=using).execute_sql(returning_fields)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1392, in execute_sql
                cursor.execute(sql, params)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/db/backends/utils.py", line 100, in execute
                return super().execute(sql, params)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/db/backends/utils.py", line 68, in execute
                return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
                return executor(sql, params, many, context)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/db/backends/utils.py", line 86, in _execute
                return self.cursor.execute(sql, params)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/db/utils.py", line 90, in __exit__
                raise dj_exc_value.with_traceback(traceback) from exc_value
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/db/backends/utils.py", line 86, in _execute
                return self.cursor.execute(sql, params)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/db/backends/sqlite3/base.py", line 396, in execute
                return Database.Cursor.execute(self, query, params)
            django.db.utils.IntegrityError: UNIQUE constraint failed: portfolio_person.user_id

The views

            import json
            from django.shortcuts import render, redirect
            from django.contrib.auth.decorators import login_required
            from django.contrib import messages
            from .models import Person, Occupation, WorkExp, AcadExp, Contact, Skills


            def portfolio(request):
                return render(request, 'portfolio/portfolio.html')

            @login_required
            def portfolio_form(request):
                if request.method == 'POST':
                    first_name=request.POST.get('firstName')
                    last_name=request.POST.get('lastName')
                    person = Person(first_name=first_name, last_name=last_name, user=request.user)
                    person.save()

                    job=request.POST.get('occupation')
                    occupation=Occupation(occupation=job, user=request.user)
                    occupation.save()

                    skillsInfo=request.POST.get('skill')
                    abilities=skillsInfo.split(',')
                    for ability in abilities:
                        skills=Skills(skills=ability, occupation_id=request.user.occupation.id)
                        skills.save()


                    workInfo=request.POST.get('workexp')
                    works=json.loads(workInfo)
                    for work in works:
                        workexp=WorkExp(company=work['company'], started=work['started'], left=work['left'], position=work['position'], user=request.user)
                        workexp.save()


                    acadInfo=request.POST.get('acadexp')
                    academics=acadInfo.split(',')
                    for acad in academics:
                        acadexp=AcadExp(education=acad, user=request.user)
                        acadexp.save()
                    

                    cell=request.POST.get('cell')
                    twitter=request.POST.get('twitter')
                    instagram=request.POST.get('instagram')
                    linkedin=request.POST.get('linkedin')
                    contact=Contact(cell=cell, twitter=twitter, instagram=instagram, linkedin=linkedin, user=request.user)
                    contact.save()
                    return redirect('portfolio')
                    messages.success(request, f'Your portfolio has been updated')


                else:
                    return render(request, 'portfolio/portfolio_form.html',)

The models

            from django.db import models
            from django.contrib.auth.models import User

            class Person(models.Model):
                user = models.OneToOneField(User, on_delete=models.CASCADE, blank=True)
                first_name = models.CharField(max_length=50)
                last_name = models.CharField(max_length=50)
                display_picture = models.ImageField(default='default.png', upload_to='display_pictures') 
                #change default jpeg#


                def __str__(self):
                    return f'{self.user.username} \'s info'
                
            class Occupation(models.Model):
                user = models.OneToOneField(User, on_delete = models.CASCADE, blank=True)
                occupation = models.CharField(max_length = 100)


                def __str__(self):
                    return f'{self.user.username} \'s occupation'

            class Skills(models.Model):
                occupation = models.ForeignKey(Occupation, on_delete=models.CASCADE)
                skills = models.CharField(max_length = 100, blank=True)
                

                def __str__(self):
                    return f'{self.occupation} \'s skillset'


            class WorkExp(models.Model):
                user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)
                company = models.CharField(max_length = 200, blank=True)
                started = models.IntegerField(null=True, blank=True)
                left = models.IntegerField(null=True, blank=True)
                position = models.CharField(max_length = 200, blank=True)


                def __str__(self):
                    return f'{self.user.username} \'s work experiences'

            class AcadExp(models.Model):  
                user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)
                education = models.CharField(max_length = 30, blank=True)

                def __str__(self):
                    return f'{self.user.username} \'s academic experiences'


            class Contact(models.Model):
                user = models.OneToOneField(User, on_delete=models.CASCADE, blank=True)
                cell = models.IntegerField()
                twitter = models.CharField(max_length = 100)
                instagram = models.CharField(max_length = 100)
                linkedin = models.CharField(max_length=100)
                

                def __str__(self):
                    return f'{self.user.username} \'s contact information'

The error message is quite explicit:
django.db.utils.IntegrityError: UNIQUE constraint failed: portfolio_person.user_id
You’re trying to create a new portfolio_person object with the same user_id as an existing portfolio_person.

You’re performing a lot of work manually that Django will do for you automatically.

I strongly suggest you review the documentation on Working with forms, and the Model API for creating model instances as compared to finding existing instances.
If you haven’t already done so, I also recommend working through either or both of the standard Django tutorial or the Django Girls Tutorial.

Thank you for your reply. Yea i am little familiar with using django forms but there are some form inputs that take multiple data before they are sent to the views which is why i opted for ajax to store the data before submitting it. Do you know a better approach i could take to solve this?

Can you explain what you mean here?

Also, can you post your form? I’d need to see that before I can offer any tangible suggestions.

Here is an image of the form below.
So the input field or set of input fields that have an add button beside them are supposed to function in a way that when the user clicks the add button the information is stored in a variable and it becomes empty and ready to take in new inputs and finally when the user submits everything is saved.

Interesting.

Most live examples I’ve seen of such things keep the previous data displayed and just add rows each time the “+” is pressed.

In either case, you could use Django’s formsets to manage them as an embedded form within the page. (Yes, you can use it multiple times as well on the same page - you could use one formset for the Skills and another for the Work experience.)

Anyway, once you’ve gathered all the data, you can then submit it all to a Django Form and process it as you would any other form submittal. That allows you to take advantage of all the Form features available - automatic mapping of submitted data to fields, custom validations if necessary, and, to resolve this current specific issue you’ve identified, the proper retrieval / updates of existing rows vs creating new ones.

(Yes, this works even if you want to only keep one entry displayed at a time - the “+” button could add an additional form to the formset, mark the current instance as hidden and display the new one.)

Wow!. This is perfect and so much more. I just read the docs through the link you added and i have to say the formsets are pretty powerful. Thank you for taking time out time explain this to me, it means a lot.