Django-Userena:向用户资料添加额外的非空字段

4 投票
1 回答
1088 浏览
提问于 2025-04-17 11:58

有没有简单的方法来设置必填的个人资料字段?

我在当前的Django项目中使用userena。我有一个自定义的个人资料,叫做UserProfile,它有一个名为start_year的字段,这个字段不能留空,也不能为null,定义如下。

class UserProfile(UserenaBaseProfile, PybbProfile):
    user = models.OneToOneField(User, unique=True,
                        verbose_name=_('user'),
                        related_name='user_profile')

    start_year = models.IntegerField(max_length=4)

我希望在注册时填写这个字段。为此,我创建了一个SignupExtraForm,定义如下,以覆盖默认的表单。

class SignupFormExtra(SignupForm):
    start_year = forms.IntegerField(label=_(u'Initiation Year'),
                            min_value=1800,
                            max_value=datetime.now().year,
                            required=True)

    def save(self):
        new_user = super(SignupFormExtra, self).save()

        new_user_profile = new_user.get_profile()

        new_user_profile.start_year = self.cleaned_data['start_year']
        new_user_profile.save()

        # Userena expects to get the new user from this form, so return the new
        # user.
        return new_user

当我尝试通过现在修改过的表单添加新用户时,出现了下面的错误:

profile_userprofile.start_year may not be NULL

错误信息的堆栈跟踪指向了new_user = super(SignupFormExtra, self).save()),在上面的代码中。

我觉得这可能是因为用户个人资料在我能提供表单中所需的数据之前就被创建和保存了。有没有简单的方法可以在用户创建过程中提供这些数据,或者推迟创建用户个人资料的时间?

谢谢,Shon

1 个回答

0

UserProfile 是在 User 被保存后,通过一个叫 post_save 的信号创建的。即使你用自己的信号来覆盖它,你也无法从那里获取表单数据。

最简单的解决办法就是允许 start_year 这个字段为空(NULL)。在数据库层面上不需要强制要求这个,反正你可以在所有表单中把这个字段设为必填:

start_year = models.IntegerField(max_length=4, blank=False, null=True)

你的自定义表单已经确保这个字段是必填的,所以你就完成了。

更新(来自评论)

是的,使用自定义表单,但你仍然可以使用 ModelForm

class MyModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(MyModelForm, self).__init__(*args, **kwargs)
        self.fields['start_year'].required = True

再次更新

其实,我在上一个更新之前没有考虑清楚。我在我的例子中给 start_year 字段加了 blank=False。这会强制所有的 ModelForm 默认要求这个字段是必填的。你根本不需要自定义的 ModelForm。不过,我保留了之前的更新以备后用。

撰写回答