博客五部曲之二 - 高级博客


582 浏览 2 years, 11 months

25 用户注册表单和视图

版权声明: 转载请注明出处 http://www.codingsoho.com/

这一节我们实现注册功能,使用实现注册视图和表单,和登陆表单不同,这次我们用ModelForm。

表单代码如下

class UserRegisterForm(forms.ModelForm):
    email = forms.EmailField(label="Email")
    email2 = forms.EmailField(label="Confirm Email")
    password = forms.CharField(widget=forms.PasswordInput) # change widget
    class Meta:
        model = User
        fields = [
            "username",
            "email",
            "email2",
            "password",
        ]
    def clean_email2(self):
        email = self.cleaned_data.get('email')
        email2 = self.cleaned_data.get('email2')
        if email != email2:
            raise forms.ValidationError("Emails must match")
        email_qs = User.objects.filter(email=email)
        if email_qs.exists():
            raise forms.ValidationError("This email has been already registered")
        return email

覆盖了password字段,默认的widget不是密码输入框
我们要保证用户名唯一且邮箱地址是正确的,所以新添加了email2这个字段,它不会保存仅数据库,仅做验证使用
表单的显示顺根据form里字段的排列顺序显示,或者通过fields进一步调节。

字段的验证是有顺序的,所以验证email只能在clean_email2函数里,如果在clean_email里,email2的clean数据还是空的。当然,你也可以直接在clean函数里做整体验证,就不需要纠结顺序了。

class UserRegisterForm(forms.ModelForm):    
    def clean(self, *args, **kwargs):
        email = self.cleaned_data.get('email')
        email2 = self.cleaned_data.get('email2')
        if email != email2:
            raise forms.ValidationError("Emails must match")
        email_qs = User.objects.filter(email=email)
        if email_qs.exists():
            raise forms.ValidationError("This email has been already registered")
        return super(UserRegisterForm, self).clean(*args, **kwargs)     

修改注册视图函数,添加相应的用户保存及登陆

def register_view(request):
    title = "Register"
    form = UserRegisterForm(request.POST or None)
    if form.is_valid():
        user = form.save(commit=False)
        password = form.cleaned_data.get('password')
        user.set_password(password)
        user.save()
        new_user = authenticate(username=user.username, password=password)
        login(request, new_user)
        return redirect("/")
    context = {
        "form":form,
    }
    return render(request, "form.html", context)    

form.save会返回一个用户数据,但这个用户数据并没有密码信息,需要通过set_password函数设置密码。同样,在调用login函数之前,必须调用authenticate,否则这个用户还是被认为anonymous用户。

最后,在登陆成功之后,都返回到主页 “/”

在URL模式表里,将posts的根目录改成了/,这样完整路径的”/”将会指向帖子列表。

注意,这种匹配表下,admin URL必须写在posts URL前面,否则admin的URL模式在posts的detail里面就匹配了,匹配成功后直接退出不会走到admin的URL,导致路径出错。

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^', include("posts.urls",namespace="posts")),
]

这样,注册功能就完成了。

我们回到列表详情页面,退出登录,发布帖子,它会报错匿名用户不需要发帖。下一节我们将会解决这个用户,必须用户登录了才允许做相关操作。