用户认证¶
用户模型¶
Django 默认提供了一个用户模型 User
,如果不符合需求可以自定义,通常继承自 AbstractBaseUser
。
AbstractBaseUser
提供了用户认证所必需的基本接口和字段,包括密码散列和令牌生成等。继承它允许你保留 Django 用户认证系统的基本功能,同时可以添加额外的字段和方法,以适应你的应用需求。
并且可以与 Django 的其他部分(如中间件、视图和表单)保持兼容,这对于使用诸如用户权限、组和会话等 Django 内置功能至关重要。
当你只想添加额外的字段或改变某些属性时,继承 AbstractUser
可能是更好的选择,它是基于 AbstractBaseUser
的,已经包含了 Django 默认用户模型的所有字段和行为。
from django.contrib.auth.models import AbstractBaseUser
class MyUser(AbstractBaseUser):
# 添加自定义字段
pass
设置中添加
AUTH_USER_MODEL = 'myapp.MyUser'
注册¶
forms.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class MyRegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ("username", "email", "password1", "password2")
views.py
from django.shortcuts import render, redirect
from .forms import MyRegistrationForm
def register(request):
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.email = form.cleaned_data['email']
user.save()
# 这里可以添加用户登录逻辑,或者重定向到登录页面
return redirect('login') # 或重定向到其他页面
else:
form = MyRegistrationForm()
return render(request, 'register.html', {'form': form})
urls.py
from django.urls import path
from .views import register
urlpatterns = [
path('register/', register, name='register'),
# 其他 URL 配置
]
templates/register.html
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Register</button>
</form>
登陆¶
forms.py
from django import forms
from django.contrib.auth.forms import AuthenticationForm
class MyLoginForm(AuthenticationForm):
# 如果需要,可以重写clean方法添加自定义验证逻辑
def clean(self):
# 调用父类的清洁方法
super().clean()
# 自定义验证逻辑
# 例如:检查额外字段的值
# some_extra_field_value = self.cleaned_data.get('some_extra_field')
# 返回清洁后的数据
return self.cleaned_data
views.py
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from .forms import MyLoginForm
# 登入
def login_view(request):
if request.method == 'POST':
form = MyLoginForm(request, data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('home') # 重定向到首页或其他页面
else:
form = MyLoginForm()
return render(request, 'login.html', {'form': form})
# 通过装饰器限制执行视图逻辑之前用户必须已登录,通用视图可以继承内置的混入类来限制
# 如果用户未登陆则默认重定向到登录页面,准确的讲是settings中设置的LOGIN_URL,默认为:/accounts/login/,另外可能还需要定义LOGIN_REDIRECT_URL和LOGOUT_REDIRECT_URL
from django.contrib.auth.decorators import login_required # 除了限制登录的装饰器外,还有限制权限的装饰器等
@login_required
def my_protected_view(request):
# 视图逻辑
urls.py
from django.urls import path
from .views import login_view
urlpatterns = [
path('login/', login_view, name='login'),
# 其他 URL 配置
]
templates/login.html
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
登出¶
- urls
from django.urls import path
from films import views
from django.contrib.auth.views import LogoutView
urlpatterns = [
path('index/', views.IndexView.as_view(), name='index'),
path('login/', views.Login.as_view(), name='login'),
path('logout/', LogoutView.as_view(), name='logout'),
path("register/", views.RegisterView.as_view(), name="register")
]
Django v4.1 版本起,LogoutView
需要使用 POST 方式请求
为了安全起见,因为注销操作可能涉及改变用户状态
<div id="navbarNav">
<ul class="navbar-nav ml-auto">
{% if user.is_authenticated %}
<form id="logout-form" method="post" action="{% url 'logout' %}">
{% csrf_token %}
<button type="submit">{% translate "Log out" %}</button>
</form>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{% url 'register' %}">Register</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'login' %}">Login</a>
</li>
{% endif %}
</ul>
</div>