Django: Ошибка внешнего ключа при расширении стандартной схемы USER
В настоящее время я борюсь с расширением модели User с помощью отношения OneToOneField
.
У меня следующая модель:
from django.db import models
from django.contrib.auth.models import User
from django.dispatch import receiver
from django.db.models.signals import post_save
# Create your models here.
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
qualified_name = models.CharField(max_length=50, blank=True)
phone_number = models.CharField(max_length=17, blank=True)
buyout = models.BooleanField(default=False)
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
Следующие формы:
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from django.core.validators import RegexValidator, ValidationError
from .models import Profile
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(widget=forms.EmailInput(
attrs={'class': 'form-control inp-xlf', 'id': 'email', 'placeholder': 'name@example.com'}),
required=True)
password1 = forms.CharField(widget=forms.PasswordInput, required=False)
password2 = forms.CharField(widget=forms.PasswordInput, required=False)
def clean(self):
cd = self.cleaned_data
email_cleaned = cd.get('email')
virtual_passwd = User.objects.make_random_password()
cd.setdefault("password1", virtual_passwd)
cd.setdefault("password2", virtual_passwd)
cd.setdefault('username', email_cleaned.split("@")[0])
return cd
class Meta:
model = User
fields = ('email',)
class ProfileRegisterForm(forms.ModelForm):
qualified_name = forms.CharField(strip=True, widget=forms.TextInput(
attrs={'class': 'form-control inp-xlf', 'id': 'name', 'placeholder': 'Enter your name...'}))
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$',
message="Phone number must be entered in the format: '+999999999'. Up to 15 digits "
"allowed.")
phone_number = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control inp-xlf', 'id': 'phone',
'placeholder': '(+41) 254 48 95'}),
validators=[phone_regex], max_length=17) # validators should be a list
buyout_checkbox = forms.BooleanField(
widget=forms.CheckboxInput(attrs={"class": "form-check-input", "id": "buyout"}), required=False)
gdpr_checkbox = forms.BooleanField(
widget=forms.CheckboxInput(attrs={"class": "form-check-input", "id": "gdpr"}),
required=True)
def clean(self):
cd = self.cleaned_data
gdpr_check = cd.get('gdpr_checkbox')
if not gdpr_check:
raise ValidationError("Mandatory fields were not provided")
return cd
class Meta:
model = Profile
fields = ('qualified_name', 'phone_number', 'buyout_checkbox', 'gdpr_checkbox')
Следующий вид:
from django.db import transaction
from django.shortcuts import render, redirect
from .forms import UserRegisterForm, ProfileRegisterForm
from django.contrib import messages
@transaction.atomic
def leads_page(request):
if request.method == "POST":
user_form = UserRegisterForm(request.POST)
profile_form = ProfileRegisterForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
username = user_form.cleaned_data.get('username')
gdpr_checkbox = profile_form.cleaned_data.get('gdpr_checkbox')
messages.success(request, f"Account created for user: {username}.")
return redirect('leads-main-page')
else:
messages.error(request, "Validation failed")
else:
user_form = UserRegisterForm()
profile_form = ProfileRegisterForm()
return render(request, 'leads/leads-page.html', context={'user_form': user_form,'profile_form': profile_form})
Установив все вышеперечисленное и выполнив: makemigrations -> migrate -> runserver, то на форме post пользователь не создается вообще и это в последствии вызывает следующую ошибку:
base.py", line 242, in _commit
return self.connection.commit()
django.db.utils.IntegrityError: FOREIGN KEY constraint failed
[12/Dec/2021 11:58:00] "POST /trucksclaims/ HTTP/1.1" 500 95351
где трассировка стека не показывает, вызывающую функцию из моего фактического исходного кода, однако, я ожидаю, что это вызвано тем, что user_form.save()
не создает никакого экземпляра пользователя. Это можно наблюдать в приложенном представлении, проверяя возвращаемое значение функции user_form.save()
.
Вопрос
Кто-нибудь знает, как решить эту проблему? Я не могу найти первопричину, чтобы немедленно приступить к исправлению.
Спасибо за любую помощь.