Fork me on GitHub

django 认证登录

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>
                        <div>
{#                            {{ form.captcha }}#}
                        </div>
                        <button type="submit" class="btn btn-primary block full-width m-b">{% trans 'Login' %}</button>

{#                        <a href="{% url 'users:forgot-password' %}">#}
                            <small>{% trans 'Forgot password' %}?</small>
                        </a>

                        <p class="text-muted text-center">
                        </p>
                    </form>
                    <p class="m-t">
                    </p>
                </div>
            </div>
        </div>
        <hr/>
        <div class="row">
            <div class="col-md-6">
                Copyright Jumpserver.org
            </div>
            <div class="col-md-6 text-right">
               <small>© 2014-2017</small>
            </div>
        </div>
    </div>
</body>
</html>

生成表信息如下:

id	password	last_login	first_name	last_name	is_active	data_joined	username	name	email	role	comment	created_bt	is_first_login
1	pbkdf2_sha256$30000$f8HLJLRwydBR$M+X1huSgQOojfaG01SGNBYPOlbYnHHw/A4/RdcSBEQQ=	11/6/2017 18:55:52	1		1	11/5/2017 18:56:05	admin	Administrator	a
posted @ 2017-11-09 16:55  patrick-py  阅读(1018)  评论(0)    收藏  举报