可是我在家里什么也没有啊,要是家里什么也没有,你会回去吗?

使用Django自带的认证模块的方法,不需要任何其他第三方的包。

转载地址1

转载地址2

转载地址3

基本配置

新建一个app,取名为users,并在settings.py的INSTALLED_APPS中加入’users’

其他的按照常规的套路走一遍即可

settings.py中设置认证的用户模型,并对语言和时区进行修改。

LANGUAGE_CODE = 'zh-hans' #修改
TIME_ZONE = 'Asia/Shanghai' #修改
AUTH_USER_MODEL = 'users.User' #添加

创建用户密码模型

自定义的用户模型,继承AbstractUser,获得username、password、email、first_name、last_name等属性,可以自己添加相关的属性。

# users/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser

# Create your models here.

class User(AbstractUser):
    nick_name = models.CharField(max_length=50, blank=True)

    class Meta(AbstractUser.Meta):
        pass

注册部分

注册表单

#users/forms.py
from django.contrib.auth.forms import UserCreationForm
from .models import User

class RegisterForm(UserCreationForm):
    class Meta(UserCreationForm.Meta):
        model = User #表单对应的模型
        fields =("username", "email") #需要渲染的控件。默认有用户名、密码、密码确认,此处增加email

注册页面

#templates/registration/register.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <link rel="stylesheet" href="https://unpkg.com/mobi.css/dist/mobi.min.css">

    <title>注册</title>
    <style>
        .errorlist{
            color: red;
        }
    </style>
</head>
<body>
    <div class="flex-center">
        <div class="container">
            <div class="flex-center">
                <div class="unit-1-2 unit-1-on-mobile">
                    <h3 class="flex-center">注册</h3>
                    <form class="form" action="{% url 'users:register' %}" method="post">
                        {% csrf_token %}
                        {% for field in form %}
								{{ field.label_tag }}
								{{ field }}
								{{ field.errors }}
								{% if field.help_text %}
									

{{ field.help_text|safe }}

{% endif %} {% endfor %} <button type="submit" class="btn btn-primary btn-block">注册</button> </form> </div> </div> </div> </div> </body> </html>

注册视图函数

#users/views.py
def register(request):
    if request.method == 'POST':
        form = RegisterForm(request.POST)

        if form.is_valid():
            form.save()
            return redirect('/')

    else:
        form = RegisterForm()
    return render(request, 'registration/register.html', context={'form': form})

在urls.py中添加注册的url

# learn_auth/urls.py:
from django.conf.urls import url, include
from django.contrib import admin
from users import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^users/', include('users.urls')),
    url(r'^users/', include('django.contrib.auth.urls')),
    url(r'^$', views.index, name='index'),
]

再user项目下添加注册url

#users/urls.py:
from django.conf.urls import url
from . import views

app_name = 'users'

urlpatterns = [
    url(r'^register/', views.register, name='register')
]

启动服务器

127.0.0.1:8000/users/register

登陆部分

Django 自带有登录的视图函数,url模式在django.contrib.auth.urls中,在工程的urls.py中添加该url即可访问到

url(r'^users/', include('django.contrib.auth.urls'))

自带的视图函数会自动检查数据库,给出登录结果,我们要做的就是提供一个模板文件,用以输入信息和显示登录结果。

登录模块默认调用templates/registration/login.html模块,因此,需要在registration目录下新建login.html

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>登录</title>
    <link rel="stylesheet" href="https://unpkg.com/mobi.css/dist/mobi.min.css">
    <style>
        .errorlist {
            color: red;
        }
    </style>
</head>
<body>
<div class="flex-center">
    <div class="container">
        <div class="flex-center">
            <div class="unit-1-2 unit-1-on-mobile">
                <h3>登录</h3>
                <form class="form" action="{% url 'login' %}" method="post">
                    {% csrf_token %}
                    {{ form.non_field_errors }}
                    {% for field in form %}
	                        {{ field.label_tag }}
	                        {{ field }}
	                        {{ field.errors }}
	                        {% if field.help_text %}
	                            

{{ field.help_text|safe }}

{% endif %} {% endfor %} <button type="submit" class="btn btn-primary btn-block">登录</button> <input type="hidden" name="next" value="{{ next }}"/> </form> <div class="flex-left top-gap text-small"> <div class="unit-2-3"><span>没有账号?<a href="{% url 'users:register' %}">立即注册</a></span></div> <div class="unit-1-3 flex-right"><span><a href="{% url 'password_reset' %}">忘记密码?</a></span></div> </div> </div> </div> </div> </div> </body> </html>

新建index.html,在其中判断用户是否已登录,若未登录则给出登录连接

使用的代码块为 URL

登出部分

注销不需要模板,直接调用{% url 'users:register' %}即可。

修改密码部分

password_change_form.html和password_change_done.html

当用户需要修改密码时,调用的自带视图函数地址为

{% url 'password_change' %}?next={{ request.path }}

需要做的,是添加修改页面和修改成功页面两个html模板

password_change_form.html
password_change_done.html

修改内容如下:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>修改密码</title>
    <link rel="stylesheet" href="https://unpkg.com/mobi.css/dist/mobi.min.css">
    <style>
        .errorlist {
            color: red;
        }
    </style>
</head>
<body>
<div class="flex-center">
    <div class="container">
        <div class="flex-center">
            <div class="unit-1-2 unit-1-on-mobile">
                <h1><a href="{% url 'index' %}">Django Auth Example</a></h1>
                <h3>修改密码</h3>
                <form class="form" action="{% url 'password_change' %}" method="post">
                    {% csrf_token %}
                    {{ form.non_field_errors }}
                    {% for field in form %}
	                        {{ field.label_tag }}
	                        {{ field }}
	                        {{ field.errors }}
	                        {% if field.help_text %}
	                            

{{ field.help_text|safe }}

{% endif %} {% endfor %} <button type="submit" class="btn btn-primary btn-block">确认修改</button> </form> </div> </div> </div> </div> </body> </html>

以及:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>密码修改成功</title>
    <link rel="stylesheet" href="https://unpkg.com/mobi.css/dist/mobi.min.css">
</head>
<body>
<div class="flex-center">
    <div class="container">
        <div>
            <h1 class="logo"><a href="{% url 'index' %}">Django Auth Example</a></h1>
            <p>密码修改成功!</p>
        </div>
    </div>
</div>
</body>
</html>

重置密码部分

需要文件

password_reset_form.html、password_reset_confirm.html、password_reset_done.html、 password_reset_complete.html

一般重置密码流程为:用户点击“忘记密码”,页面跳转到reset_form.html,输入邮箱和相关信息,点击提交,页面跳转到reset_done页面。后台发送重置邮件给用户,并提供重置密码的页面地址,用户打开reset_confirm页面,设置新的密码并提交,页面跳转到reset_complete页面。

django自带发邮件的功能,只需要在settings.py中进行相关配置,如下面的配置是把邮件发送给终端

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

调用自带重置密码的

url:{% url 'password_reset' %}

reset_form和reset_conform的主要部分的内容如下(reset_done和reset_complete只是简单的静态提示内容)

password_reset_form.html :

<form class="form" action="{% url 'password_reset' %}" method="post">
                    {% csrf_token %}
                    {{ form.non_field_errors }}
                    {% for field in form %}
	                        {{ field.label_tag }}
	                        {{ field }}
	                        {{ field.errors }}
	                        {% if field.help_text %}
	                            

{{ field.help_text|safe }}

{% endif %} {% endfor %} <button type="submit" class="btn btn-primary btn-block">提交</button> </form>

password_reset_confirm.html

<form class="form" method="post">
                    {% csrf_token %}
                    {{ form.non_field_errors }}
                    {% for field in form %}
	                        {{ field.label_tag }}
	                        {{ field }}
	                        {{ field.errors }}
	                        {% if field.help_text %}
	                            

{{ field.help_text|safe }}

{% endif %} {% endfor %} <button type="submit" class="btn btn-primary btn-block">提交</button> </form>

扩展

自带的模块只能通过用户名和密码来认证,如果想要登录时可以通过邮件等其他方式来认证,需要自定义认证模块。

在users目录下新建backends.py,实现authenticate和get_user方法

from .models import User

class EmailBackend(object):
    def authenticate(self, request, **credentials):
        # 要注意登录表单中用户输入的用户名或者邮箱的 field 名均为 username
        email = credentials.get('email', credentials.get('username'))
        try:
            user = User.objects.get(email=email)
        except User.DoesNotExist:
            pass
        else:
            if user.check_password(credentials["password"]):
                return user

    def get_user(self, user_id):
        """
        该方法是必须的
        """
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

配置settings.py:

AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',
    'users.backends.EmailBackend',
)

django自带的验证机制

from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout  #登入和登出

from django.contrib.auth.decorators import login_required  # 验证用户是否登录

def acc_login(request):


    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")

        user = authenticate(username=username,password=password)  
        # 类型为<class 'django.contrib.auth.models.User'>

        # print(type(models.Customer.objects.get(name="赵凡")))
        # print(user,type(user))
        if user:

            login(request,user)  # 验证成功之后登录
            return  redirect('/crm')

    return render(request, "login.html")


def acc_logout(request):

    logout(request)  # 登出

    return redirect("/login")

必须登录之后才能访问页面

from django.contrib.auth.decorators import login_required

@login_required  # 加上这个装饰器就是限制必须登录才能执行这个函数
def dashboard(request):
    print(request.user)

    return render(request, "crm1/dashboard.html")

如果加了@login_required,页面跳转会有问题,解决方法如下
在setting里追加一下内容/login/跟URL是一致的

LOGIN_URL = "/login/"

其他资料

创建用户

Django默认提供了用户权限管理模块auth,在我们第一次数据库迁移时,他就自动帮我们在数据库中创建三张表:

user表,User是auth模块中维护用户信息的表,在数据库中该表被命名为auth_user. 该表继承自Abstractuser.

group表,定义用户组模型,该表只包含一个name字段和一个permissions(权限)多对多关系字段,在数据库中被命名为auth_group.

Permission, 权限表,提供表级别的权限控制,可以检查用户是否对某个表拥有增(add),改(change),删(delete)权限。

从数据库生成的表来看,这三张表实现了两两多对多的关联,其中用户和组生成的第三张表是

auth_user_groups,group和permission生成的第三张表是auth_group_permissions,用户和权限生成的第三张表是auth_user_user_permissions。这里我们主要介绍下user表。

User表

在auth中user继承自AbstractUser,其中AbstractUser又继承自AbstractBaseUser和PermissionsMixin,其中AbstractBaseUser只保存了密码和登陆时间,PermissionsMixin提供了权限先关的字段,比如:is、_superuser和组合权限表之间的关联。

User对象的字段

password:Django默认保存是加密后的密码,无法直接看到明文密码
last_login:上一次登陆时间
is_superuser:是否是超级管理员,是为1,否为0
username:用户名
first_name
last_name
email:邮箱
is_staff:用户是否拥有网站的管理权限
is_active:是否允许用户登录, 设置为 False,可以在不删除用户的前提下禁止用户登录。
data_joined:账户创建日期
groups: 与组多对多关联的字段
user_permissions: 与权限关联的多对多字段,也就是是说明了为什么第三张表表为auth_user_user_permissions. 表名(user)+字段名(user_permissions)

类属性

is_authenticated:判断是否被认证,即是否登陆
is_anonymous: 是否为匿名用户
username_validator:指向用于验证用户名的验证实例,默认是validators.UnicodeUsernameValidator

类方法

get_username():  获取用户名
get_full_name(): 获取全名,即first_name+空格+last_name
get_short_name():获取first_name
set_password(raw_password): 设置密码,如果raw_password是None,则密码将被设置为不可用的密码,就像使用了 set_unusable_password() 一样。
check_password(raw_password): 检查密码是否正确。
set_unusable_password():将用户标记为未设置密码,即密码为None
has_usable_password():返回该用户是否未设置密码
get_group_permissions(): 获取这个用户所在组中所具有的的全部权限。
has_perm(): 判断一个用户是否具有某个权限。
has_perms(perm_list): 判断用户对一个权限列表是否具有权限。
has_module_perms(package_name): 判断对app是否有权限。

Auth模块常用方法

创建用户

python manage.py createsuperuser
python manage.py createuser

模块导入

from django.contrib import auth

authenticate()

提供了用户认证功能,即验证用户名以及密码是否正确,一般需要username 、password两个关键字参数。如果认证成功(用户名和密码正确有效),便会返回一个 User 对象。authenticate()会在该 User 对象上设置一个属性来标识后端已经认证了该用户,且该信息在后续的登录过程中是需要的,认证失败返回None。

user = auth.authenticate(username='theuser',password='thepassword')

login(HttpRequest, user)

该函数接受一个HttpRequest对象,以及一个经过认证的User对象。该函数实现一个用户登录的功能。它本质上会在后端为该用户生成相关session数据。

def my_view(request):
    username = request.POST['username']
    password = request.POST['password']
    user = auth.authenticate(username=username, password=password)
    if user is not None:
        auth.login(request, user)
        # Redirect to a success page.
        ...
    else:
    # Return an 'invalid login' error message.

logout(request):

该函数接受一个HttpRequest对象,无返回值。当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。

def logout_view(request):
    auth.logout(request)
    # Redirect to a success page.

is_authenticated():

用来判断当前请求是否通过了认证。

def my_view(request):
    if not request.user.is_authenticated():
    return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))

login_requierd():

auth 给我们提供的一个装饰器工具,用来快捷的给某个视图函数添加登录校验。

from django.contrib.auth.decorators import login_required

@login_required
def my_view(request):
    ...

若用户没有登录,则会跳转到django默认的 登录URL ‘/accounts/login/ ‘ 并传递当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。如果需要自定义登录的URL,则需要在settings.py文件中通过LOGIN_URL进行修改。 LOGIN_URL = ‘/login/‘ # 这里配置成你项目登录页面的路由

method_decorator():

auth 给我们提供的一个装饰器工具,用来快捷的给某个类视图添加登录校验。

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator

class Home(views.View):

    @method_decorator(login_required)
    def get(self, request):
        return render(request, 'home.html')

create_user():

auth 提供的一个创建新用户的方法,需要提供必要参数(username、password)等。

from django.contrib.auth.models import User

user = User.objects.create_user(username = '用户名', password = '密码', email = '邮箱', ...)
check_password(password)

create_superuser():

auth 提供的一个创建新的超级用户的方法,需要提供必要参数(username、password)等。

from django.contrib.auth.models import User

user = User.objects.create_superuser(username = '用户名', password = '密码', email = '邮箱', ...)
check_password(password)