Django自定义认证User模型email字段不能保存为空的解决办法
在一个项目中直接使用了自定义Django AdminSite作为后台管理网站。
在修改自定义User模型的信息后,点击保存按钮提交Form时,提示email字段不能为空。
这是因为我们的UserAdmin类继承自django.contrib.auth.admin.UserAdmin,在父类UserAdmin的form中将email字段定义为了required,即必填字段。
通过继承django.contrib.auth.forms.UserChangeForm类,并在__init__方法中对email字段属性进行修改,可以实现我们想要的效果。
1 | from django.contrib.auth.forms import UserChangeForm |
这样在保存时就不会提示email字段不能为空了。
但是测试中发现,如果不填写email字段内容,保存后发现email字段的值变成了空字符串,而不是None,但是我们在自定义User模型中指定了email字段null=True,即我们期望的它应该是一个空值None。
经过调试后发现,在django.contrib.admin.options.ModelAdmin类的_changeform_view方法代码中,调用form.is_valid()方法后,email字段的值发生了变化。
1 | # django.contrib.admin.options.ModelAdmin |
于是顺藤摸瓜,找到django.forms.models.BaseModelForm类中_post_clean方法,发现在此方法中调用了Model实例的full_clean方法。
1 | # django.forms.models.BaseModelForm |
继续跟进发现在自定义User模型的父类AbstractUser中,实现了clean方法,并且对email字段的值进行了修改。
1 | # django.contrib.auth.models.AbstractUser |
这里调用的normalize_email是django.contrib.auth.base_user.BaseUserManager中实现的一个静态方法。
1 | # django.contrib.auth.base_user |
所以我们只需要自己实现一个UserManager类并继承BaseUserManager类,并重写normalize_email方法。
1 | from django.contrib.auth.models import BaseUserManager |
这样,当提交Form中缺少email值时,就能正确的把email字段值保存为None了。
Django自定义认证User模型email字段不能保存为空的解决办法
https://blog.dennic365.com/2019/03/19/django-user-model-email-null/