Django中Shahadati_user模型保存时触发NOT NULL约束失败错误的解决求助
Django中Shahadati_user模型保存时触发NOT NULL约束失败错误的解决求助
问题描述
我正在构建一个包含两种用户类型的网站,需要基于AbstractUser模型创建两个用户配置文件。但当我通过表单提交数据到数据库时,出现了错误:"NOT NULL constraint failed: app_shahadati_user.user_id"。我尝试了多种方法,但所有方法都只将用户保存到User模型中,而我希望将数据保存到Shahadati_user模型中。
我的代码
models.py
from django.contrib.auth.models import AbstractUser, BaseUserManager from django.db import models from django.utils.translation import gettext_lazy as _ class CustomUserManager(BaseUserManager): def create_user(self, email, password=None, **extra_fields): if not email: raise ValueError(_('The Email must be set')) email = self.normalize_email(email) user = self.model(email=email, **extra_fields) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, password=None, **extra_fields): extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) if extra_fields.get('is_staff') is not True: raise ValueError(_('Superuser must have is_staff=True.')) if extra_fields.get('is_superuser') is not True: raise ValueError(_('Superuser must have is_superuser=True.')) return self.create_user(email, password, **extra_fields) class CustomUser(AbstractUser): username = None email = models.EmailField(_("email address"), unique=True) USERNAME_FIELD = "email" REQUIRED_FIELDS = [] objects = CustomUserManager() def __str__(self): return self.email class Shahadati_user(models.Model): user = models.OneToOneField(CustomUser, on_delete=models.CASCADE) user_nID=models.PositiveIntegerField() def __str__(self): return self.user.email
forms.py
from django import forms from .models import CustomUser, Shahadati_user class CustomUserCreateForm(forms.ModelForm): password = forms.CharField(widget=forms.PasswordInput) password_validation = forms.CharField(widget=forms.PasswordInput) class Meta: model = CustomUser fields = ['first_name','last_name','email'] def clean_password_validation(self): pwd1 = self.cleaned_data.get('password') pwd2 = self.cleaned_data.get('password_validation') if pwd1 and pwd2 and pwd1 != pwd2: raise forms.ValidationError("Passwords don't match") return pwd2 def save(self, *args, **kwargs): self.instance.set_password(self.cleaned_data.get('password')) return super().save(*args, **kwargs) class ShahadatiUserForm(forms.ModelForm): class Meta: model = Shahadati_user fields =['user_nID']
views.py
from django.shortcuts import render from .forms import CustomUserCreateForm, ShahadatiUserForm def user_reg(request): if request.method == 'POST': form = CustomUserCreateForm(request.POST, request.FILES) form_ShU = ShahadatiUserForm(request.POST,request.FILES) if form.is_valid() and form_ShU.is_valid(): form.save() form_ShU.save() else: pass return render(request, 'Register.html', {})
错误追踪
Traceback (most recent call last): File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\db\backends\utils.py", line 89, in _execute return self.cursor.execute(sql, params) File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\db\backends\sqlite3\base.py", line 357, in execute return Database.Cursor.execute(self, query, params) The above exception (NOT NULL constraint failed: app_shahadati_user.user_id) was the direct cause of the following exception: File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\core\handlers\exception.py", line 55, in inner response = get_response(request) File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "D:\university\graduationProject\Shahadati\app\views.py", line 30, in user_reg form_ShU.save() File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\forms\models.py", line 548, in save self.instance.save() File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\db\models\base.py", line 831, in save self.save_base( File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\db\models\base.py", line 882, in save_base updated = self._save_table( File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\db\models\base.py", line 1025, in _save_table results = self._do_insert( File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\db\models\base.py", line 1066, in _do_insert return manager._insert( File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\db\models\manager.py", line 85, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\db\models\query.py", line 1790, in _insert return query.get_compiler(using=using).execute_sql(returning_fields) File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\db\models\sql\compiler.py", line 1657, in execute_sql cursor.execute(sql, params) File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\db\backends\utils.py", line 103, in execute return super().execute(sql, params) File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\db\backends\utils.py", line 67, in execute return self._execute_with_wrappers( File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\db\backends\utils.py", line 80, in _execute_with_wrappers return executor(sql, params, many, context) File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\db\backends\utils.py", line 84, in _execute with self.db.wrap_database_errors: File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\db\utils.py", line 91, in __exit__ raise dj_exc_value.with_traceback(traceback) from exc_value File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\db\backends\utils.py", line 89, in _execute return self.cursor.execute(sql, params) File "C:\Users\dandy\miniconda3\envs\djangoEnv\lib\site-packages\django\db\backends\sqlite3\base.py", line 357, in execute return Database.Cursor.execute(self, query, params) Exception Type: IntegrityError at /user_reg/ Exception Value: NOT NULL constraint failed: app_shahadati_user.user_id
解决方案
问题的核心是:你保存ShahadatiUserForm时,没有把刚创建的CustomUser实例关联到Shahadati_user对象上,导致user这个一对一字段为空,触发了NOT NULL约束。
修改你的views.py,步骤如下:
- 保存
CustomUserCreateForm时,接收返回的用户实例 - 把这个用户实例赋值给
ShahadatiUserForm的instance的user字段 - 再保存
ShahadatiUserForm
修改后的views.py代码:
from django.shortcuts import render from .forms import CustomUserCreateForm, ShahadatiUserForm def user_reg(request): if request.method == 'POST': form = CustomUserCreateForm(request.POST) form_ShU = ShahadatiUserForm(request.POST) if form.is_valid() and form_ShU.is_valid(): # 先保存CustomUser,获取用户实例 custom_user = form.save() # 获取Shahadati_user实例,关联刚创建的custom_user shahadati_user = form_ShU.save(commit=False) # commit=False表示先不保存到数据库 shahadati_user.user = custom_user shahadati_user.save() # 现在保存到数据库 # 把表单对象传回模板,方便显示错误信息 return render(request, 'Register.html', {'form': form, 'form_ShU': form_ShU}) # GET请求时,初始化空表单 else: form = CustomUserCreateForm() form_ShU = ShahadatiUserForm() return render(request, 'Register.html', {'form': form, 'form_ShU': form_ShU})
另外还有几个小建议:
- 表单里的
password和password_validation建议使用PasswordInput组件,这样输入时会隐藏密码,提升用户体验(我已经在forms.py示例里修改了) - 你的
CustomUserManager可能缺失了,我在models.py里补充了完整的实现,否则创建用户时可能会报错 - 视图里的
request.FILES可以去掉,因为你的表单里没有文件上传字段,不需要传这个参数 - 不要用
pass处理表单无效的情况,应该把表单对象传回模板,这样可以显示错误信息给用户
这样修改后,就能正确将CustomUser和Shahadati_user关联起来,避免NOT NULL约束错误了。
备注:内容来源于stack exchange,提问作者Dania Al haj hassan
相关产品推荐
相关产品推荐

