1. 程式人生 > >DAY86-Django框架(十六) auth元件

DAY86-Django框架(十六) auth元件

auth模組

1.定義

我們在開發一個網站的時候,無可避免的需要設計實現網站的使用者系統。此時我們需要實現包括使用者註冊、使用者登入、使用者認證、登出、修改密碼等功能,這還真是個麻煩的事情呢。

Django作為一個完美主義者的終極框架,當然也會想到使用者的這些痛點。它內建了強大的使用者認證系統--auth,它預設使用 auth_user 表來儲存使用者資料

2.基本使用

  • create_user()

    功能:

    ​ auth 提供的一個建立新使用者的方法,需要提供必要引數(username、password)等

    語法:

from django.contrib.auth.models import User
user = User.objects.create_user(username=name,password=pwd)
  • create_superuser()

    功能:

    ​ auth 提供的一個建立新的超級使用者的方法,需要提供必要引數(username、password)等

    語法:

from django.contrib.auth.models import User
user = User.objects.create_superuser(username=name,password=pwd)
  • authenticate()

    功能:

    ​ 提供了使用者認證功能,一般使用使用者名稱和密碼驗證,其本質就是拿著引數和資料庫比對,都正確便返回User物件,否則返回一個None

    語法:

from django.contrib.auth import authenticate
user = authenticate(username=name,password=pwd)
print(user)#列印的是使用者名稱
  • login(HttpRequest,user)

    功能:

    ​ 該函式接受一個HttpRequest物件,以及一個經過認證的User物件。該函式實現一個使用者登入的功能。它本質上會在後端為該使用者生成相關session資料。一定要是認證通過的才可以登入。

    語法:

from django.contrib.auth import authenticate,login
user = authenticate(username=name,password=pwd)
login(request,user)
  • logout(request)

    功能:

    ​ 該函式接受一個HttpRequest物件,無返回值。當呼叫該函式時,資料庫和cookie裡的當前的session都會全部清除。該使用者即使沒有登入,使用該函式也不會報錯。

    語法:

from django.contrib.auth import logout
logout(request)
  • is_authenticated()

    功能:

    ​ 用來判斷當前請求是否通過了認證並且登陸。

    語法:

from django.contrib.auth import logout
user = authenticate(username=name,password=pwd)
login(request,user)
print(request.user.is_authenticated())
  • login_requierd()

    功能:

    ​ auth 給我們提供的一個裝飾器工具。如果是沒有登陸的話會跳轉

    語法:

from django.contrib.auth.decorators import login_required

@login_required(redirect_field_name=REDIRECT_FIELD_NAME, login_url=None)
#redirect_field_name:是url中?後的字串,預設是REDIRECT_FIELD_NAME,也就是next
#login_url:跳轉的路徑,預設是/accounts/login/,也可以指定
#如果想要全域性設定跳轉路徑,在setting檔案裡寫LOGIN_URL='指定路徑'
  • check_password(password)

    功能:

    ​ auth 提供的一個檢查密碼是否正確的方法,需要提供當前請求使用者的密碼。

    語法:

print(request.user.check_password(pwd))#返回True/False
  • set_password(password)

    功能:

    ​ auth 提供的一個修改密碼的方法,接收 要設定的新密碼 作為引數。對當前使用者的密碼修改。修改完一定要呼叫save()方法儲存

    語法:

request.user.set_password('123')
request.user.save()
  • is_staff

    功能:

    ​ 用來判斷當前使用者是否擁有網站的管理許可權。可以設定,但是也要呼叫save()來儲存

    語法:

print(request.user.is_staff)
  • is_active

    功能:

    ​ 是否允許使用者登入, 設定為 False,可以在不刪除使用者的前提下禁止使用者登入。可以設定,但是也要呼叫save()來儲存

    語法:

print(request.user.is_active)

3.擴充套件的User表

​ 由於當前使用的User表是Django為我們已經建立好的,欄位都寫死了,一旦我們有其他欄位的需求,就無法完成。所以為了使用者表的靈活性,有兩種方法解決。

方式一

新建一張表,存放使用者的額外資訊,通過一對一的方式,連結到User表

from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class UserInfo(models.Model):
    phone=models.CharField(max_length=32)
    user = models.OneToOneField(to=User)#不能加引號,不然只會在本檔案找User

方式二

auth模組的User就是繼承AbstractUser,那麼我們可以新建一個表模型繼承AbstractUser,這樣的話之前用到User這個表模型的地方,都要換成UserInfo

from django.contrib.auth.models import AbstractUser

class UserInfo(AbstractUser):
    phone = models.CharField(max_length=32)
    sex = models.BooleanField()
    
    
#setting.py
AUTH_USER_MODEL='app01.UserInfo'#不然資料庫遷移會失敗

4.案例

簡單登入,註冊,登出

模板元件

base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>
        {% block title %}
            Titl
        {% endblock %}
    </title>
    {% load static %}
    <link rel="stylesheet" href="{% get_static_prefix %}bootstrap-3.3.7-dist/css/bootstrap.css">
    <script src="{% static 'jquery-3.3.1.js' %}"></script>
    <style>
        {% block css %}

        {% endblock %}
    </style>
</head>
<body>
{% csrf_token %}
<nav class="navbar navbar-default">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <a class="navbar-brand" href="#">社團活動管理</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav navbar-right">
        {% block head-r %}

        {% endblock %}
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>
{% block middle %}
{% endblock %}
</body>
<script>
    {% block js %}
    {% endblock %}
</script>
</html>

子元件:head-right.html

<li><a href="{% url 'login' '.html' %}">登入</a></li>
<li><a href="{% url 'register' '.html' %}">註冊</a></li>

head_right_login.html

<li><a href="#">{{ name }}</a></li>
<li><a href="/logoff/">登出</a></li>

註冊

基於form元件,auth元件和ajax的註冊

from app01.models import UserInfo
from django import forms
from django.forms import widgets
class User_from(forms.Form):
    name = forms.CharField(label='使用者名稱', max_length=10, min_length=3,
                           widget=widgets.TextInput({'class': 'form-control'}),
                           error_messages={'max_length': '最長是8', 'min_length': '最短是3', 'required': '不能為空'}, )
    pwd = forms.CharField(label='密碼', max_length=10, min_length=3,
                          widget=widgets.PasswordInput({'class': 'form-control'}),
                          error_messages={'max_length': '最長是8', 'min_length': '最短是3', 'required': '不能為空'})
    re_pwd = forms.CharField(label='確認密碼', max_length=10, min_length=3,
                             widget=widgets.PasswordInput({'class': 'form-control'}),
                             error_messages={'max_length': '最長是8', 'min_length': '最短是3', 'required': '不能為空'})

    def clean(self):
        pwd = self.cleaned_data.get('pwd')
        re_pwd = self.cleaned_data.get('re_pwd')
        if pwd != re_pwd:
            raise ValidationError('兩次密碼不一致')
        return self.cleaned_data
    
    
def register(request, html):
    dic = {'msg': None, 'errors': None, 'all': None}
    if request.method == 'GET':
        form = User_from()
        return render(request, 'register.html', locals())
    if request.method == 'POST':
        form = User_from(request.POST)
        if form.is_valid():
            UserInfo.objects.create_user(username=request.POST.get('name'), password=request.POST.get('pwd'))
            dic['msg'] = '註冊成功'
        else:
            all = form.errors.get('__all__')
            dic['msg'] = '註冊失敗'
            dic['errors'] = form.errors
            dic['all'] = all
        print(dic)
        return JsonResponse(dic)
    
import json
def blur(request):
    msg=''
    if request.method == 'POST':
        name = request.POST.get('name')
        res = UserInfo.objects.filter(username=name).first()
        if res:
            msg='該使用者已存在'
        return HttpResponse(json.dumps(msg))

模板層

{% extends 'base.html' %}
{% block title %}
    註冊
{% endblock %}
{% block css %}
    h1{
    margin:0 auto;
    text-align:center;
    }
{% endblock %}
{% block head-r %}
    {% include 'head_right.html' %}
{% endblock %}
{% block middle %}
    <h1 class="h1">註冊</h1>
    <div class="col-md-4 col-md-offset-4 ">
        <form>
            {% for foo in form %}
                <div class="form-group">
                    <label>{{ foo.label }}</label>
                    {{ foo }}
                </div>
            {% endfor %}
        </form>
        <button id="btn">註冊</button>
    </div>
{% endblock %}
{% block js %}
    $('#btn').click(function () {
    var da = {
    'name': $('#id_name').val(),
    'pwd': $('#id_pwd').val(),
    're_pwd': $('#id_re_pwd').val(),
    'email': $('#id_email').val(),
    'csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val(),
    }
    $.ajax({
    url: '{% url 'register' '.html' %}',
    data: da,
    type: 'post',
    success: function (data) {
        let ids = [];
        $('input').each(function () {
            id = $(this).attr('id');
            ids.push(id)
        });

        {#頁面顯示錯誤資訊#}
        for (let i in data.errors) {
            let id_name = 'id_' + i;
                for (let j = 0; j < ids.length; j++) {
                    if (id_name == ids[j]){
                    $('#' + ids[j]).prev('span').remove()
                    let aa='<spanstyle="height:20px;color:red;float:right">' + data.errors[i] + '</span>';
                    $('#' + ids[j]).before(aa)
                    }
                }
        }

        {#頁面顯示全域性錯誤資訊#}
        if (data.all) {
            $('#btn + span').text('')
            $('#btn').after('<span style="color:red;float:right">' + data.all + '</span>')
        }

        {#頁面顯示註冊是否成功#}
        $('h1').html('<span style="color:red">' + data.msg + '</span>');

        setTimeout(function () {
            location.reload()
            },3000)
        }
    })
    });

    $('#id_name').blur(function () {
    var bb = {'name':$('#id_name').val(),'csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()}
    $.ajax({
    url: '/blur/',
    data: bb,
    type: 'post',
    dataType:'json',
    success: function (data) {
    let bb = $('<span style="height:20px;color:red;float:right" id="abc">' + data + '</span>')
    $('#id_name').before(bb)

    }
    })
    });

    $('#id_name').focus(function () {
    $('#id_name').prev('span').remove()
    {#$('#abc').remove()#}
    })
{% endblock %}

登入

from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
from django.contrib import auth
def login(request, html):
    if request.method == 'POST':
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        user = auth.authenticate(username=name, password=pwd)
        print(user)
        if user is not None:
            auth.login(request, user)
            print(123)
            return redirect("/index/")
    return render(request, 'login.html')

login.html

{% extends 'base.html'%}
{% block title %}
    登入
{% endblock %}
{% block css %}
    h1{
     margin:0 auto;
     text-align:center;
    }
{% endblock %}
{% block head-r %}
    {% include 'head_right.html' %}
{% endblock %}
{% block middle %}
<h1 class="h1">登入</h1>
<form  method="post" class="col-md-4 col-md-offset-4 ">
  <div class="form-group">
      {% csrf_token %}
    <label >使用者名稱</label>
    <input type="text" class="form-control"  name="name">
  </div>
  <div class="form-group">
    <label for="exampleInputPassword1">密碼</label>
    <input type="password" class="form-control" id="exampleInputPassword1" name="pwd">
  </div>
    <input type="submit" value="登入">
</form>
{% endblock %}

首頁

from django.shortcuts import render, HttpResponse, redirect
def index(request):
    #判斷是否登陸
    if not request.user.is_authenticated():
        flag = 0
    else:
        name = request.user.username
        flag = 1
    return render(request, 'index.html', locals())

index.html

{% extends 'base.html' %}
{% block title %}
    首頁
{% endblock %}
{% block css %}
    h1{
    margin:0 auto;
    text-align:center;
    }
{% endblock %}
{% block head-r %}
    {% if flag%}
        {% include 'head_right_login.html' %}
    {% else %}
        {% include 'head_right.html' %}
    {% endif %}
{% endblock %}
{% block middle %}
    <h1 class="h1">首頁</h1>
{% endblock %}

登出

def logoff(request):
    auth.logout(request)
    return redirect('/index/')