Ошибка формы Django: django.db.utils.IntegrityError: UNIQUE constraint failed: legal_useragreedtolegal.user_id
Когда я вызываю form.save(), я получаю "django.db.utils.IntegrityError: UNIQUE constraint failed: legal_useragreedtolegal.user_id"
Я думаю, что это может быть потому, что у меня есть oneToOneField и Django пытается сохранить в UserAgreedToLegal и User Model, но модель User уже имеет этот ID, поэтому уникальное ограничение не работает, но не уверен.
Мне интересно, как я могу решить эту проблему. Я перечислил свою модель, форму и код представления ниже
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()
Результатом является
django.db.utils.IntegrityError: UNIQUE constraint failed: legal_useragreedtolegal.user_id
Я думаю, это может быть потому, что у меня есть
OneToOneField
и Django пытается сохранить в UserAgreedToLegal и User Model, но модель User уже имеет этот ID, поэтому уникальное ограничение не работает, но не уверен.
Вы правы, OneToOneField
по сути является ForeignKey
с unique=True
. Поэтому нет смысла посещать это представление второй раз.
Вы можете проверить, согласился ли человек с юридическими условиями, и если это так, перенаправить его на страницу, например, на представление, которое отображает страницу, объясняющую, что пользователь уже согласился, например, что-то вроде:
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':
# …
# …
где name-of-some-view
должны указывать на представление, которое будет рендерить эту страницу.
Причина, по которой он не срабатывал, заключалась в том, что существовало отношение "один к одному" с моделью пользователя django, и когда я вызывал form.save(), он пытался сохранить новую строку (вставить нового пользователя) как в User, так и в мою модель, а затем он видел, что этот user_id уже существует в моей модели, и он говорил мне, что это невозможно сделать, потому что тогда это нарушало бы правило, которое я установил, о наличии только отношения "один к одному", потому что если бы он сохранил каждого пользователя, у него было бы много записей. Это создаст отношения один ко многим вместо отношений один к одному.
Вместо этого мне нужно было сказать django, что я не хочу вставлять новую запись в мою модель, или обновить ее, если такая запись уже существует, а если нет, то создать ее, сохраняя связь с моделью User.
Мне нужно было передать экземпляр, чтобы Django Forms знал, что у меня уже есть эта модель и я не хочу обновлять этот экземпляр.
вот код, который сработал для меня
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()