Whenever, I call form.save() I get " django.db.utils.IntegrityError: UNIQUE constraint failed: legal_useragreedtolegal.user_id "
I think this might be because I have a oneToOneField and Django is trying to save to UserAgreedToLegal and User Model but the User model already has that ID, so the unique constraint fails, but not sure.
I am wondering how I can fix this issue. I listed my model, form, and view code below
models.py
import uuid
from django.contrib.auth.models import User
from django.db import models
from django.utils import timezone as django_timezone
class UserAgreedToLegal(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
agreed_first_terms_of_service = models.BooleanField(default=False, blank=False, null=False)
date_agreed = models.DateField(null=True, default=django_timezone.now)
uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
def __str__(self):
return self.user.username
forms.py
from django import forms
from legal.models import UserAgreedToLegal
class TermsOfServiceAgreementForm(forms.ModelForm):
class Meta:
model = UserAgreedToLegal
fields = [
'agreed_first_terms_of_service'
]
views.py
if request.method == 'POST':
form = TermsOfServiceAgreementForm(request.POST)
if form.is_valid():
form.clean()
terms_of_service_agreement = form.save(commit=False)
terms_of_service_agreement.user = request.user
terms_of_service_agreement.save()
The result is
django.db.utils.IntegrityError: UNIQUE constraint failed: legal_useragreedtolegal.user_id
I think this might be because I have a
OneToOneField
and Django is trying to save to UserAgreedToLegal and User Model but the User model already has that ID, so the unique constraint fails, but not sure.
You are correct, a OneToOneField
is in essence a ForeignKey
with unique=True
. It thus makes no sense to visit this view a second time.
You can check if the person already has agreed to the legal terms, and if that is the case redirect to a page, for example a view that renders a page to explain that the user already agreed, so something like:
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
@login_required
def my_view(request):
if UserAgreedToLegal.objects.filter(user=request.user).exists():
return redirect('name-of-some-view')
if request.method == 'POST':
# …
# …
where the name-of-some-view
should point to a view that will render that page.
The reason it was failing was because there was a OneToOne relationship with the django user model, and when I called form.save() it was trying to save a new row (insert a new user) into both User and my model and then it would see that this user_id already exists in my model and it would tell me that it cannot be done because then it would violate a rule that I placed of having only a one to one relationship because if it did save each one user would have many records. That would create a one to many instead of a one to one.
Instead, what I needed to do was to tell django that I don't want to insert a new record in my model, or to update it if that record already exists and if not create it while maintaining its relationship with the User model.
I had to pass in an instance for Django Forms to know that I already have this model and I don't want to update this instance.
here is the code that worked for me
if request.method == 'POST':
my_user = UserAgreedToLegal.objects.get_or_create(user=request.user)[0]
form = TermsOfServiceAgreementForm(request.POST, instance=my_user)
if form.is_valid():
form.clean()
terms = form.save(commit=False)
terms.user = request.user
terms.save()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.