You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,步骤如下:

  1. 保存CustomUserCreateForm时,接收返回的用户实例
  2. 把这个用户实例赋值给ShahadatiUserForm的instance的user字段
  3. 再保存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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 09:52:49