IntegrityError: UNIQUE constraint failed: usermanager_userprofile.email_address
IntegrityError: UNIQUE constraint failed: usermanager_userprofile.email_address
我正在开发一个使用带有 OneToOneField 的用户模型的注册应用程序。
models.py
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.db import models
from django.dispatch import receiver
class UserProfile(models.Model):
GENDER_CHOICES = (
('M', 'Male'),
('F', 'Female'),
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField('First name', max_length=30)
surname = models.CharField('Last name', max_length=150)
gender = models.CharField('Gender', max_length=1, choices=GENDER_CHOICES)
date_of_birth = models.DateField('Date of birth', null=True)
profile_image = models.ImageField('Profile image', upload_to='users_upload/profiles/%Y/%m/%d')
company_name = models.CharField('Company Name', max_length=75, blank=True, null=True)
fiscal_data = models.CharField('Fiscal data', max_length=200)
city = models.CharField('City', max_length=150)
address = models.CharField('Address', max_length=200)
postcode = models.CharField('Zip Code', max_length=50)
country = models.CharField('Country', max_length=75)
telephone_number = models.CharField('Telephone', max_length=20)
email_address = models.EmailField('Email')
class Meta:
unique_together = ['fiscal_data', 'email_address']
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.userprofile.save()
forms.py
from django import forms
from django.contrib.auth import get_user_model, password_validation
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import UserProfile
class UserForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'password1', 'password2')
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = [
'name', 'surname', 'gender', 'date_of_birth',
'user_type', 'profile_image', 'company_name',
'address', 'postcode', 'city', 'country',
'telephone_number', 'email_address',
'fiscal_data',
]
views.py
from django.contrib.auth.forms import UserCreationForm
from django.db import transaction
from django.shortcuts import render
from .forms import UserProfileForm
from .models import UserProfile
@transaction.atomic
def createUser(request):
if request.method == 'POST':
user_form = UserCreationForm(request.POST)
profile_form = UserProfileForm(request.POST or None, request.FILES or None)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.refresh_from_db()
profile_form = UserProfileForm(request.POST, instance=user.userprofile)
profile_form.full_clean()
profile_form.save()
else:
user_form = UserCreationForm()
profile_form = UserProfileForm()
return render(request, 'usermanager/editing/create_user.html', {
'user_form': user_form,
'profile_form': profile_form
})
create_user.html
<form method="POST" enctype="multipart/form-data" novalidate>{% csrf_token %}
<div class="card-body">
{{ user_form.as_p }}
{{ profile_form.as_p }}
</div>
<div class="card-footer">
<div class="row justify-content-md-center">
<div class="col-md-auto">
<input type="submit" class="btn btn-danger shadow" value="Create Profile">
</div>
</div>
</div>
</form>
当我尝试使用表单注册新用户时,我看到了这条错误消息:
UNIQUE constraint failed: usermanager_userprofile.email_address
即使我尝试使用管理面板注册新用户,也会发生这种情况。
我该如何解决这个问题?
我用过this strategy to create my model, for for createUser view I've used this.
回溯:
Environment:
Request Method: POST Request URL: http://127.0.0.1:8000/create-user/
Django Version: 2.2.5 Python Version: 3.6.8 Installed Applications:
['django.contrib.admin', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.staticfiles', 'kernel',
'usermanager'] Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback:
File
"/home/max/Django/area-test/app_usermanager_dev/devenv/lib/python3.6/site-packages/django/core/handlers/exception.py"
in inner
34. response = get_response(request)
File
"/home/max/Django/area-test/app_usermanager_dev/devenv/lib/python3.6/site-packages/django/core/handlers/base.py"
in _get_response
115. response = self.process_exception_by_middleware(e, request)
File
"/home/max/Django/area-test/app_usermanager_dev/devenv/lib/python3.6/site-packages/django/core/handlers/base.py"
in _get_response
113. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python3.6/contextlib.py" in inner
52. return func(*args, **kwds)
File
"/home/max/Django/area-test/app_usermanager_dev/app_usermanager/usermanager/views.py"
in createUser
30. profile_form.save() # Gracefully save the form
File
"/home/max/Django/area-test/app_usermanager_dev/devenv/lib/python3.6/site-packages/django/forms/models.py"
in save
453. 'created' if self.instance._state.adding else 'changed',
Exception Type: ValueError at /create-user/ Exception Value: The
UserProfile could not be changed because the data didn't validate.
在您的 UserProfile
模型中,有一个字段:
email_address = models.EmailField('Email', unique=True)
当您添加 unique=True
时,这意味着该字段对于该模型中的所有条目都是唯一的。您可以删除该关键字参数和 运行 makemigrations 并迁移。或者您需要为每个 UserProfile
条目输入唯一的电子邮件地址。
更新:
发生错误的原因可能是您在第二次启动配置文件时没有验证它:
profile_form = UserProfileForm(request.POST, instance=user.userprofile)
profile_form.full_clean()
# before calling save, you need to call profile_form.is_valid()
profile_form.save()
TBH,我认为你应该删除你的 post 保存信号 create_user_profile
和 save_user_profile
,因为它使你的 createUser
方法的实施过于复杂。此外,如果您没有创建 UserProfile
的机制但您有一个表单可以做到这一点,那么 post 保存信号将很有用,那么为什么需要信号?
如果删除这些信号,请尝试以下代码:
def createUser(request):
if request.method == 'POST':
user_form = UserCreationForm(request.POST)
profile_form = UserProfileForm(request.POST or None, request.FILES or None)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
profile_form = profile_form.save(commit=False)
profile_form.user = user
profile_form.save()
仅供参考,按照 pep8 标准命名方法时,您应该使用 snake_case
。所以最好将 createUser
命名为 create_user
.
当我试图防止字符串相同时出现此错误,即使它具有不同的大写字母。
示例狗和狗不应该工作。
代码示例
class Category(models.Model):
name = CICharField(max_length=255, unique=True, error_messages={'unique':"This category has already been registered."})
def __str__(self):
return self.name
def save(self, force_insert=False, force_update=False):
self.name = self.name.lower()
self.name = capitalizeFirtChar(self.name)
super(Category, self).save(force_insert, force_update)
上面这段代码给了我错误,我通过在保存函数中添加这个 if 语句解决了这个问题
之前
def save(self, force_insert=False, force_update=False):
self.name = self.name.lower()
self.name = capitalizeFirtChar(self.name)
super(Category, self).save(force_insert, force_update)
之后
def save(self, force_insert=False, force_update=False):
self.name = self.name.lower()
self.name = capitalizeFirtChar(self.name)
# If the name already exists
if not Category.objects.filter(name__iexact=self.name).exists():
super(Category, self).save(force_insert, force_update)
我正在开发一个使用带有 OneToOneField 的用户模型的注册应用程序。
models.py
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.db import models
from django.dispatch import receiver
class UserProfile(models.Model):
GENDER_CHOICES = (
('M', 'Male'),
('F', 'Female'),
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField('First name', max_length=30)
surname = models.CharField('Last name', max_length=150)
gender = models.CharField('Gender', max_length=1, choices=GENDER_CHOICES)
date_of_birth = models.DateField('Date of birth', null=True)
profile_image = models.ImageField('Profile image', upload_to='users_upload/profiles/%Y/%m/%d')
company_name = models.CharField('Company Name', max_length=75, blank=True, null=True)
fiscal_data = models.CharField('Fiscal data', max_length=200)
city = models.CharField('City', max_length=150)
address = models.CharField('Address', max_length=200)
postcode = models.CharField('Zip Code', max_length=50)
country = models.CharField('Country', max_length=75)
telephone_number = models.CharField('Telephone', max_length=20)
email_address = models.EmailField('Email')
class Meta:
unique_together = ['fiscal_data', 'email_address']
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.userprofile.save()
forms.py
from django import forms
from django.contrib.auth import get_user_model, password_validation
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import UserProfile
class UserForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'password1', 'password2')
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = [
'name', 'surname', 'gender', 'date_of_birth',
'user_type', 'profile_image', 'company_name',
'address', 'postcode', 'city', 'country',
'telephone_number', 'email_address',
'fiscal_data',
]
views.py
from django.contrib.auth.forms import UserCreationForm
from django.db import transaction
from django.shortcuts import render
from .forms import UserProfileForm
from .models import UserProfile
@transaction.atomic
def createUser(request):
if request.method == 'POST':
user_form = UserCreationForm(request.POST)
profile_form = UserProfileForm(request.POST or None, request.FILES or None)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.refresh_from_db()
profile_form = UserProfileForm(request.POST, instance=user.userprofile)
profile_form.full_clean()
profile_form.save()
else:
user_form = UserCreationForm()
profile_form = UserProfileForm()
return render(request, 'usermanager/editing/create_user.html', {
'user_form': user_form,
'profile_form': profile_form
})
create_user.html
<form method="POST" enctype="multipart/form-data" novalidate>{% csrf_token %}
<div class="card-body">
{{ user_form.as_p }}
{{ profile_form.as_p }}
</div>
<div class="card-footer">
<div class="row justify-content-md-center">
<div class="col-md-auto">
<input type="submit" class="btn btn-danger shadow" value="Create Profile">
</div>
</div>
</div>
</form>
当我尝试使用表单注册新用户时,我看到了这条错误消息:
UNIQUE constraint failed: usermanager_userprofile.email_address
即使我尝试使用管理面板注册新用户,也会发生这种情况。
我该如何解决这个问题?
我用过this strategy to create my model, for for createUser view I've used this.
回溯:
Environment:
Request Method: POST Request URL: http://127.0.0.1:8000/create-user/
Django Version: 2.2.5 Python Version: 3.6.8 Installed Applications: ['django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'kernel', 'usermanager'] Installed Middleware: ['django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback:
File "/home/max/Django/area-test/app_usermanager_dev/devenv/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner 34. response = get_response(request)
File "/home/max/Django/area-test/app_usermanager_dev/devenv/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response 115. response = self.process_exception_by_middleware(e, request)
File "/home/max/Django/area-test/app_usermanager_dev/devenv/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response 113. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python3.6/contextlib.py" in inner 52. return func(*args, **kwds)
File "/home/max/Django/area-test/app_usermanager_dev/app_usermanager/usermanager/views.py" in createUser 30. profile_form.save() # Gracefully save the form
File "/home/max/Django/area-test/app_usermanager_dev/devenv/lib/python3.6/site-packages/django/forms/models.py" in save 453. 'created' if self.instance._state.adding else 'changed',
Exception Type: ValueError at /create-user/ Exception Value: The UserProfile could not be changed because the data didn't validate.
在您的 UserProfile
模型中,有一个字段:
email_address = models.EmailField('Email', unique=True)
当您添加 unique=True
时,这意味着该字段对于该模型中的所有条目都是唯一的。您可以删除该关键字参数和 运行 makemigrations 并迁移。或者您需要为每个 UserProfile
条目输入唯一的电子邮件地址。
更新:
发生错误的原因可能是您在第二次启动配置文件时没有验证它:
profile_form = UserProfileForm(request.POST, instance=user.userprofile)
profile_form.full_clean()
# before calling save, you need to call profile_form.is_valid()
profile_form.save()
TBH,我认为你应该删除你的 post 保存信号 create_user_profile
和 save_user_profile
,因为它使你的 createUser
方法的实施过于复杂。此外,如果您没有创建 UserProfile
的机制但您有一个表单可以做到这一点,那么 post 保存信号将很有用,那么为什么需要信号?
如果删除这些信号,请尝试以下代码:
def createUser(request):
if request.method == 'POST':
user_form = UserCreationForm(request.POST)
profile_form = UserProfileForm(request.POST or None, request.FILES or None)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
profile_form = profile_form.save(commit=False)
profile_form.user = user
profile_form.save()
仅供参考,按照 pep8 标准命名方法时,您应该使用 snake_case
。所以最好将 createUser
命名为 create_user
.
当我试图防止字符串相同时出现此错误,即使它具有不同的大写字母。
示例狗和狗不应该工作。
代码示例
class Category(models.Model):
name = CICharField(max_length=255, unique=True, error_messages={'unique':"This category has already been registered."})
def __str__(self):
return self.name
def save(self, force_insert=False, force_update=False):
self.name = self.name.lower()
self.name = capitalizeFirtChar(self.name)
super(Category, self).save(force_insert, force_update)
上面这段代码给了我错误,我通过在保存函数中添加这个 if 语句解决了这个问题
之前
def save(self, force_insert=False, force_update=False):
self.name = self.name.lower()
self.name = capitalizeFirtChar(self.name)
super(Category, self).save(force_insert, force_update)
之后
def save(self, force_insert=False, force_update=False):
self.name = self.name.lower()
self.name = capitalizeFirtChar(self.name)
# If the name already exists
if not Category.objects.filter(name__iexact=self.name).exists():
super(Category, self).save(force_insert, force_update)