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.