简体   繁体   中英

Django form error: django.db.utils.IntegrityError: UNIQUE constraint failed: legal_useragreedtolegal.user_id

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM