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/')