AbstractUser
from django.contrib.auth.models import AbstractUser AbstractBaseUser中只含有3个field: password, last_login和is_active. 这个就是你自己高度定制自己需要的东西
什么是基于扩展AbstractBaseUser来创建的自定义用户模型?
它是继承于AbstractBaseUser类的一个全新的用户系统。这需要通过settings.py进行特别的维护和更新一些相关的文件。理想的情况是,它在项目开始时就已经被设计,因为它对数据库架构影响很大。在执行时都需要额外的维护。
什么时候需要扩展AbstractBaseUser类自定义用户模型呢?
当应用对验证过程具有特殊要求时,那么需要自定义一个用户模型。比如,在一些将邮件地址代替用户名作为验证令牌的情况时,自定义用户模型更合适。
方法4:扩展AbstractUser来创建自定义用户模型
什么是基于扩展AbstractUser创建的自定义用户模型?
它是继承于AbstractUser类的一个全新的用户系统。它也需要通过settings.py进行特别的维护和更新一些相关的文件。理想的情况是,它在项目开始之前就已经被设计,因为它对数据库架构影响很大。在执行时需要额外的维护。
什么时候需要扩展AbstractBaseUser类的自定义用户模型呢?
当你对Django处理身份验证过程很满意而又不会改动它时,那可以使用它。或者,你想直接在用户模型中增加一些额外的信息而不想创建新的类时,也可以使用它。
is_staff
是否允许user访问admin界面
is_active
用户是否活跃。
一、重写user,将新的user注册到admin,还要重写认证
二、继承user,进行扩展(记得在settings中设置AUTH_USER_MODEL
settings.py 设置AUTH_USER_MODEL = "myapp.NewUser"
# Custom User Auth model
AUTH_USER_MODEL = 'users.User'
2.1 继承AbstractUser类
from django.contrib.auth.models import AbstractUser
from django.utils.translation import ugettext_lazy as _
from django.db import models
from django.conf import settings
from . import UserGroup
__all__ = ['User']
class User(AbstractUser):
ROLE_CHOICES = (
('Admin', _('Administrator')),
('User', _('User')),
('App', _('Application'))
)
username = models.CharField(max_length=20, unique=True, verbose_name=_('Username'))
name = models.CharField(max_length=20, verbose_name=_('Name'))
email = models.EmailField(max_length=30, unique=True, verbose_name=_('Email'))
groups = models.ManyToManyField(UserGroup, related_name='users', blank=True, verbose_name=_('User group'))
role = models.CharField(choices=ROLE_CHOICES, default='User', max_length=10, blank=True, verbose_name=_('Role'))
is_first_login = models.BooleanField(default=False)
comment = models.TextField(max_length=200, blank=True, verbose_name=_('Comment'))
created_by = models.CharField(max_length=30, default='', verbose_name=_('Created by'))
@property
def is_superuser(self):
if self.role == 'Admin':
return True
else:
return False
@is_superuser.setter
def is_superuser(self, value):
if value is True:
self.role = 'Admin'
else:
self.role = 'User'
@property
def is_staff(self):
if self.is_authenticated and self.is_valid:
return True
else:
return False
@is_staff.setter
def is_staff(self, value):
pass
踩过的坑:
1、登陆的时候用自带的认证模块总是报none
user = authenticate(username=username, password=password)
查看源码发现是check_password的方法是用hash进行校验,之前注册的password写法是
user.password=password
这种写法是明文入库,需要更改密码的入库写法
user.set_password(password)
form 设置
from django import forms
from django.contrib.auth.forms import AuthenticationForm
from django.utils.translation import gettext_lazy as _
class UserLoginForm(AuthenticationForm):
username = forms.CharField(label=_('Username'), max_length=100)
password = forms.CharField(
label=_('Password'), widget=forms.PasswordInput, max_length=100,
strip=False)
AuthenticationForm登录表单
用于用户登录的表单。
默认情况下,AuthenticationForm 将拒绝is_active 标志为False 的用户。
login.py配置
from django.shortcuts import render,HttpResponse
from django.shortcuts import reverse, redirect
from django.contrib.auth import login as auth_login, logout as auth_logout
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_protect
from django.views.generic.edit import FormView
from .. import forms
from django.views.decorators.cache import never_cache
from django.views.decorators.debug import sensitive_post_parameters
@method_decorator(csrf_protect, name='dispatch')
class UserLoginView(FormView):
template_name = 'users/login.html'
form_class = forms.UserLoginForm
redirect_field_name = 'next'
def get(self, request, *args, **kwargs):
if request.user.is_staff:
return redirect(self.get_success_url())
return super(UserLoginView, self).get(request, *args, **kwargs)
def form_valid(self, form):
auth_login(self.request, form.get_user())
return redirect(self.get_success_url())
def get_success_url(self):
if self.request.user.is_first_login:
return reverse('users:user-first-login')
return self.request.POST.get(
self.redirect_field_name,
self.request.GET.get(self.redirect_field_name, reverse('index')))
登陆login
login()
登陆函数,需要一个HttpRequest对象和一个User对象作参数。login()使用django的session框架,将User的id存储在session中。
同时使用authenticate()和login():
from django.contrib.auth import authenticate, login
def my_view(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
# Redirect to a success page.
else:
# Return a 'disabled account' error message
else:
# Return an 'invalid login' error message.
如果不知道密码,login方法:
user=MyUser.objects.get(...)
user.backend = 'django.contrib.auth.backends.ModelBackend'
login(request,user)
FormView使用基于类的视图处理表单 表单的处理通常有3 个步骤:
- 初始的GET (空白或预填充的表单)
- 带有非法数据的POST(通常重新显示表单和错误信息)
- 带有合法数据的POST(处理数据并重定向) 使用FormView 来构造其视图:
from myapp.forms import ContactForm
from django.views.generic.edit import FormView
class ContactView(FormView):
template_name = 'contact.html'
form_class = ContactForm
success_url = '/thanks/'
def form_valid(self, form):
# This method is called when valid form data has been POSTed.
# It should return an HttpResponse.
form.send_email()
return super(ContactView, self).form_valid(form)
html设置:
{% load static %}
{% load i18n %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title> JumpServer </title>
<link rel="shortcut icon" href="{% static "img/facio.ico" %}" type="image/x-icon">
{% include '_head_css_js.html' %}
<link href="{% static "css/jumpserver.css" %}" rel="stylesheet">
<script src="{% static "js/jumpserver.js" %}"></script>
<style>
.captcha {
float: right;
}
</style>
</head>
<body class="gray-bg">
<div class="loginColumns animated fadeInDown">
<div class="row">
<div class="col-md-6">
</div>
<div class="col-md-6">
<div class="ibox-content">
<div><img src="{% static 'img/logo.png' %}" width="82" height="82"> <span class="font-bold text-center" style="font-size: 32px; font-family: inherit">{% trans 'Login' %}</span></div>
<form class="m-t" role="form" method="post" action="">
{% csrf_token %}
{% if form.errors %}
{% if 'captcha' in form.errors %}
<p class="red-fonts">{% trans 'Captcha invalid' %}</p>
{% else %}
<p class="red-fonts">{{ form.non_field_errors.as_text }}</p>
{% endif %}
{% endif %}
<div class="form-group">
<input type="text" class="form-control" name="{{ form.username.html_name }}" placeholder="{% trans 'Username' %}" required="">
</div>
<div class="form-group">
<input type="password" class="form-control" name="{{ form.password.html_name }}" placeholder="{% trans 'Password' %}" required="">
</div>
<