Django: Auth: Customizing

 20th August 2020 at 2:19pm

Django 的 auth 系统提供了一整套非常实用的 API,包括 Model、View、Template 等等。它默认是以 username 作为用户的唯一标识的。

常见的需求是换成 email 来标识用户。Django 的 文档 提供了一个例子,但缺了 View 相关的部分。Practical Django 2 and Channels 2 一书的第 3 章有一个跟官网近似,但是更完整的实现。

  • Model 层:编写自定义的 User model 及它的 manager
    • 对于登录的 form,它应该负责校验用户的用户名密码是否正确,并初始化 session(使用 django.contrib.auth 中的 authenticate, login API)
  • Form 层:编写相关的 Form,基本上是重写一套类似于 django.contrib.auth.forms 中的 UserCreationForm, UserChangeForm 等实现
  • View 层:
    • 编写注册新用户的 view,来实现展示注册页面(GET)以及处理注册请求(POST);下面有一个实际的代码
    • 对于如登录、登出、修改密码等过程,可以直接用 django.contrib.auth.views 中提供的 View,如 LoginView, LogoutView 等;如果它不足够满足你的需求,比如你想在登录过程插一段你自己的逻辑,那么你可以继承它实现一个自定义的
  • URL 层:加上相应的路径映射规则使得浏览器可以访问这些页面和接口;下面有一个实际的代码
  • Admin:编写 UserAdmin 的定义使得 Django Admin 可以正常工具

Signup View Example

from django.contrib.auth import authenticate, login

class SignupView(FormView):
    template_name = 'main/signup.html'
    form_class = forms.UserCreationForm

    def get_success_url(self):
        redirect_to = self.request.GET.get("next", "/")
        return redirect_to

    def form_valid(self, form):
        response = super().form_valid(form)

        form.save()

        email = form.cleaned_data.get("email")
        raw_password = form.cleaned_data.get("password1")
        logger.info(f"New signup for email {email}")

        user = authenticate(email=email, password=raw_password)
        login(self.request, user)

        form.send_mail()
        messages.info(self.request, "You signed up successfully.")

        return response

URL Example

from django.contrib.auth import views as auth_views
from django.urls import path

from main import views, models, forms

urlpatterns = [
    # ...
		
    path('signup/', views.SignupView.as_view(), name="signup"),
    path('login/', auth_views.LoginView.as_view(
        template_name='main/login.html', form_class=forms.AuthenticationForm
    ), name="signup"),
]