从 ModelForm 提交 POST 变量后的完整性错误(Django 中的扩展用户模型)



我正在创建一个员工注册页面来创建一个新用户(没有人登录,即匿名用户)。我有一个配置文件模型(添加其他字段,如部门、别名等),它从 Django 中的用户模型扩展而来。我将用户引用为配置文件的一对一关系。

当新员工注册时,他们必须从引用Staff_Type表中的 ModelChoiceField 中指定他们的"员工类型ID"("职位")。User表不存储"stafftypeid",所以我扩展了UserCreationForm。

我的问题是我可以通过表单成功提交 POST 变量,用户 (auth_user) 将创建一个新记录。我可以在 Django/admin 页面中看到新用户。但是,配置文件将无法创建随附的新记录,并且我收到错误("完整性错误在/register/(1048, "列'staffTypeID'不能为空")")。奇怪的是,我有所有的 POST 变量,但配置文件表中字段所需的变量没有传递。

这是继承问题吗?只有在创建新用户时,才应创建新的配置文件记录。

我尝试遵循Corey Schafer Django教程8,Simpleisbetterthancomplex(https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html#onetoone)和Stack Overflow中的教程和其他代码。

我还尝试重写def form.save(),然后将我的表单分成两部分(最初只是一个),因为它应该在数据库端更容易处理。我真的很感激这里的建议!

管理员\models.py: (Staff_Type)

from django.db import models
from decimal import Decimal
class Staff_Type(models.Model):
stafftypeid = models.AutoField(db_column='staffTypeID', primary_key=True)  
stafftypedesc = models.CharField(db_column='staffTypeDesc', max_length=150)
class Meta:
ordering = ['stafftypedesc']
unique_together = ('stafftypedesc',)
db_table = 'stafftype'
def __str__(self):
return self.stafftypedesc

用户\models.py:

from django.db import models
from django.contrib.auth.models import User
from decimal import Decimal

class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
stafftypeid = models.ForeignKey('Administrator.Staff_Type', models.DO_NOTHING, db_column='staffTypeID')
employeeid = models.CharField(max_length=20)
alias = models.CharField(max_length=20)
department = models.CharField(max_length=150)
organization = models.CharField(max_length=150)
fte = models.DecimalField(max_digits=4, decimal_places=1, default=Decimal(100.0))

def __str__(self):
return f'{self.user.username} Profile'

用户\signals.py:

from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile

@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()

用户\注册.html:

{% extends "Administrator/adminBase.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="col-md-8">
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Register New User </legend>
{{ user_form|crispy }}
{{ profile_form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Sign Up</button>
</div>
</form>
</div>
</div>
{% endblock content %}

用户\forms.py:


from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from Administrator.models import Staff_Type
from .models import Profile
from .models import Profile
from django.utils.translation import ugettext_lazy as _

class UserRegisterForm(UserCreationForm):
email = forms.EmailField(max_length=150, label = "Email")
first_name = forms.CharField(max_length=150, label = "First Name")
last_name = forms.CharField(max_length=150, label = "Surname")
class Meta:
model = User
fields = ['username', 'email', 'first_name', 'last_name', 'password1', 'password2']

class ProfileForm(forms.ModelForm):
stafftypeid = forms.ModelChoiceField(queryset=Staff_Type.objects.all(), empty_label="Staff Type")
employeeid = forms.CharField(max_length=20, label="Employee ID")
alias = forms.CharField(max_length=20, label="Alias")
department = forms.CharField(max_length=150, label="Department")
organization = forms.CharField(max_length=150, label="Organization")
fte = forms.DecimalField(max_digits=4, decimal_places=1, min_value=0.0, max_value=100.0, label="FTE(%)")
class Meta:
model = Profile
fields = ['stafftypeid', 'employeeid', 'alias', 'department', 'organization', 'fte']

用户\views.py:

from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import UserRegisterForm, ProfileForm

def register(request):
if request.method == "POST":
user_form = UserRegisterForm(request.POST)
profile_form = ProfileForm(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')
stafftypeid = profile_form.cleaned_data.get('stafftypeid')
messages.success(request, f'Account created for {username}, with alias: {stafftypeid}')
return redirect('admin-home')
else:
user_form = UserRegisterForm()
profile_form = ProfileForm()
return render(request, 'users/register.html', {'user_form': user_form, 'profile_form': profile_form})

用户\apps.py:

from django.apps import AppConfig

class UsersConfig(AppConfig):
name = 'users'
def ready(self):
import users.signals

信号中发生错误。在那里,您只需创建一个配置文件,只设置用户字段,而不设置任何其他字段。

你不需要这个信号。您将在单独的配置文件窗体中创建配置文件并将其保存在视图中。您应该删除这两个信号。

然后,更新视图:

if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()

(另外,请停止将您的外键命名为以"_id"结尾;它们不是 ID,它们是实际的相关对象。

最新更新