Django 扩展 UserCreationForm:密码未保存
在本文中,我们将介绍如何使用Django的UserCreationForm扩展类来创建用户,并解决出现密码未保存的问题。我们将通过示例说明这个问题,并提供解决方案。
阅读更多:Django 教程
问题描述
当我们使用Django的UserCreationForm来创建新用户时,我们期望用户输入的密码能够被安全地保存到数据库中。但是,在某些情况下,密码却没有被正确保存,导致用户无法成功登录。
问题分析
要解决这个问题,我们首先需要了解UserCreationForm是如何工作的。UserCreationForm是Django内置的一个表单类,用于创建用户。它继承自forms.ModelForm,并添加了一些额外的字段和验证方法。
当我们提交UserCreationForm表单时,Django会先执行表单的验证方法clean,然后根据验证的结果创建用户对象并保存到数据库中。在创建用户对象时,会调用User类的set_password方法对密码进行加密,并保存到数据库中的password字段。
然而,在某些情况下,我们发现用户提交的密码并没有被正确地保存到数据库中。原因是在我们扩展UserCreationForm时,可能没有正确地继承其父类方法,导致密码没有被正确加密和保存。
示例代码
下面我们通过示例代码来演示这个问题,并提供解决方案。
首先,在我们的项目中创建一个名为forms.py的文件,并导入必要的模块:
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
然后,我们定义一个新的表单类MyUserCreationForm,继承自UserCreationForm,并添加一个额外的字段email:
class MyUserCreationForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
接下来,在views.py文件中,我们导入MyUserCreationForm,并在视图函数中使用它来创建用户:
from django.shortcuts import render
from .forms import MyUserCreationForm
def register(request):
form = MyUserCreationForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
form.save()
return redirect('home')
return render(request, 'register.html', {'form': form})
在模板文件register.html中,我们使用form.as_p将表单呈现为一个简单的HTML表格:
<form method="POST" action="{% url 'register' %}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Register</button>
</form>
现在我们可以运行我们的应用程序并尝试使用这个注册表单来创建新用户。然而,当我们在注册表单中输入用户名、电子邮件地址和密码时,我们发现密码并没有被正确地保存到数据库中。
解决方案
要解决这个问题,我们需要在我们的MyUserCreationForm类中正确地继承UserCreationForm的方法。具体步骤如下:
首先,在我们的MyUserCreationForm类中添加一个构造方法,并调用父类的构造方法:
class MyUserCreationForm(UserCreationForm):
email = forms.EmailField()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
然后,我们需要重写save方法,以便在保存用户之前,正确地设置用户的密码:
from django.contrib.auth import get_user_model
class MyUserCreationForm(UserCreationForm):
email = forms.EmailField()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class Meta:
model = get_user_model()
fields = ['username', 'email', 'password1', 'password2']
现在,我们再次运行我们的应用程序,并使用更新后的注册表单来创建新用户。我们会发现,这次密码正确地保存到了数据库中,我们可以成功登录了。
总结
在本文中,我们通过示例代码演示了如何使用Django的UserCreationForm扩展类来创建用户,并解决了密码未保存的问题。我们提供了一种解决方案,通过正确地继承和重写UserCreationForm的方法,成功地保存了用户输入的密码。希望本文能对使用Django扩展UserCreationForm的开发者有所帮助。