Django:forms局部函數、cookie、sesion、auth模塊

1、forms組件javascript

2、cookie和session組件css

3、auth組件html

 

1、forms組件java

  1.校驗字段功能python

  針對一個實例:註冊用戶講解jquery

模型:models數據庫

class UserInfo(models.Model):
    name=models.CharField(max_length=32)
    pwd=models.CharField(max_length=32)
    email=models.EmailField(

模板文件django

複製代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>

<form action="" method="post">
    {% csrf_token %}
    <div>
        <label for="user">用戶名</label>
        <p><input type="text" name="name" id="name"></p>
    </div>
    <div>
        <label for="pwd">密碼</label>
        <p><input type="password" name="pwd" id="pwd"></p>
    </div>
    <div>
        <label for="r_pwd">確認密碼</label>
        <p><input type="password" name="r_pwd" id="r_pwd"></p>
    </div>
     <div>
        <label for="email">郵箱</label>
        <p><input type="text" name="email" id="email"></p>
    </div>
    <input type="submit">
</form>

</body>
</html>

視圖函數編程

# forms組件
from django.forms import widgets

wid_01=widgets.TextInput(attrs={"class":"form-control"})
wid_02=widgets.PasswordInput(attrs={"class":"form-control"})

class UserForm(forms.Form):
    name=forms.CharField(max_length=32,
                         widget=wid_01
                         )
    pwd=forms.CharField(max_length=32,widget=wid_02)
    r_pwd=forms.CharField(max_length=32,widget=wid_02)
    email=forms.EmailField(widget=wid_01)
    tel=forms.CharField(max_length=32,widget=wid_01)



def register(request):

    if request.method=="POST":
        form=UserForm(request.POST)
        if form.is_valid():
            print(form.cleaned_data)       # 全部乾淨的字段以及對應的值
        else:
            print(form.cleaned_data)       #
            print(form.errors)             # ErrorDict : {"校驗錯誤的字段":["錯誤信息",]}
            print(form.errors.get("name")) # ErrorList ["錯誤信息",]
        return HttpResponse("OK")
    form=UserForm()
    return render(request,"register.html",locals())

  2.渲染標籤功能bootstrap

渲染方式1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
   <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<h3>註冊頁面</h3>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-lg-offset-3">

                <form action="" method="post">
                    {% csrf_token %}
                    <div>
                        <label for="">用戶名</label>
                        {{ form.name }}
                    </div>
                    <div>
                        <label for="">密碼</label>
                        {{ form.pwd }}
                    </div>
                    <div>
                        <label for="">確認密碼</label>
                        {{ form.r_pwd }}
                    </div>
                    <div>
                        <label for=""> 郵箱</label>
                        {{ form.email }}
                    </div>

                    <input type="submit" class="btn btn-default pull-right">
                </form>
        </div>
    </div>
</div>



</body>
</html>

渲染方式二

<form action="" method="post">
                    {% csrf_token %}
                    
                    {% for field in form %}
                        <div>
                            <label for="">{{ field.label }}</label>
                            {{ field }}
                        </div>
                    {% endfor %}
                    <input type="submit" class="btn btn-default pull-right">
                
</form>

渲染方式3、

<form action="" method="post">
    {% csrf_token %}
    
    {{ form.as_p }}

    <input type="submit" class="btn btn-default pull-right">

</form>

  三、渲染錯誤信息功能

視圖

def register(request):

    if request.method=="POST":
        form=UserForm(request.POST)
        if form.is_valid():
            print(form.cleaned_data)       # 全部乾淨的字段以及對應的值
        else:
            print(form.cleaned_data)       #
            print(form.errors)             # ErrorDict : {"校驗錯誤的字段":["錯誤信息",]}
            print(form.errors.get("name")) # ErrorList ["錯誤信息",]
        return render(request,"register.html",locals())
    form=UserForm()
    return render(request,"register.html",locals()

模板

<form action="" method="post" novalidate>
    {% csrf_token %}
    
    {% for field in form %}
        <div>
            <label for="">{{ field.label }}</label>
            {{ field }} <span class="pull-right" style="color: red">{{ field.errors.0 }}</span>
        </div>
    {% endfor %}
    <input type="submit" class="btn btn-default">

</form>

組件參數配置

class Ret(Form):
    name = forms.CharField(max_length=10, min_length=2, label='用戶名',
                           error_messages={'required': '該字段不能爲空', 'invalid': '格式錯誤', 'max_length': '太長',
                                           'min_length': '過短'},
                           widget=widgets.TextInput(attrs={'class':'form-control'}))
    pwd = forms.CharField(max_length=10, min_length=2, widget=widgets.PasswordInput(attrs={'class':'form-control'}))
    email = forms.EmailField(label='郵箱', error_messages={'required': '該字段不能爲空', 'invalid': '格式錯誤'})

  5.局部鉤子

from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
def clean_name(self):

        val=self.cleaned_data.get("name")

        ret=UserInfo.objects.filter(name=val)

        if not ret:
            return val
        else:
            raise ValidationError("該用戶已註冊!")

    def clean_tel(self):

        val=self.cleaned_data.get("tel")

        if len(val)==11:

            return val
        else:
            raise  ValidationError("手機號格式錯誤")

  6.全局鉤子

  def clean(self):
        pwd=self.cleaned_data.get('pwd')
        r_pwd=self.cleaned_data.get('r_pwd')

        if pwd and r_pwd:
            if pwd==r_pwd:
                return self.cleaned_data
            else:
                raise ValidationError('兩次密碼不一致')
        else:

            return self.cleaned_data
pwd_err=my_form.errors.get('__all__')
from django import forms
from django.forms import widgets
from app01 import models
from django.core.exceptions import ValidationError


class RegForm(forms.Form):
    name = forms.CharField(max_length=8, min_length=3, label='用戶名',
                           error_messages={'max_length': '太長了',
                                           'min_length': '過短了',
                                           'required': '該項不能爲空'
                                           },
                           widget=widgets.TextInput(attrs={'class': 'form-control'})
                           )
    pwd = forms.CharField(max_length=8, min_length=3, label='密碼',
                          error_messages={'max_length': '太長了',
                                          'min_length': '過短了',
                                          'required': '該項不能爲空'
                                          },
                          widget=widgets.PasswordInput(attrs={'class': 'form-control'})
                          )
    re_pwd = forms.CharField(max_length=8, min_length=3, label='確認密碼',
                          error_messages={'max_length': '太長了',
                                          'min_length': '過短了',
                                          'required': '該項不能爲空'
                                          },
                          widget=widgets.PasswordInput(attrs={'class': 'form-control'})
                          )
    email = forms.EmailField(label='郵箱', error_messages={'invalid': '格式不正確',
                                                         'required': '該項不能爲空'
                                                         },
                             widget=widgets.EmailInput(attrs={'class': 'form-control'})
                             )
    # clean_字段名字
    def clean_name(self):
        # 從cleaned_data中取出字段的值
        name = self.cleaned_data.get('name')
        # # 校驗是否以sb開頭
        if name.startswith('sb'):
            raise ValidationError('不能以sb開頭')
        else:
            return name
        # user = models.UserInfo.objects.filter(name=name).first()
        # if user:
        #     # 用戶已經存在,校驗不經過,拋一個異常
        #     raise ValidationError('該用戶已經存在')
        #
        # else:
        #     # 校驗經過,返回要校驗的數據
        #     return name
    # def clean_pwd(self):
    #     pass
    # 全局鉤子函數(上面全部校驗規則都經過了,包括自定義的)
    def clean(self):
        pwd=self.cleaned_data.get('pwd')
        re_pwd=self.cleaned_data.get('re_pwd')
        if pwd==re_pwd:
            # 正確,返回self.cleaned_data
            return None
        else:
            # 校驗失敗,拋異常
            raise ValidationError('兩次密碼不一致')
myfroms
from django.shortcuts import render, HttpResponse, redirect

# Create your views here.
from app01.MyForm import RegForm


def register(request):
    if request.method == 'GET':
        myform = RegForm()
    else:
        myform = RegForm(request.POST)
        if myform.is_valid():
            # 存數據庫,保存這我的
            print(myform.cleaned_data)
        else:
            # 校驗不經過,這裏面也可能有值
            # 總錯誤信息{'name':['太長了',],'pwd':['過短了']}
            # print(myform.cleaned_data)
            # 總錯誤
            # myform.glo_err=myform.errors.get('__all__')
            error_all = myform.errors.get('__all__')
            # print()
            # 每個的錯誤信息
            # for item in myform:
            #     # ['太長了',]
            #     # print(item.errors[0])
            #     # print(type(item.errors))
            #     from django.forms.utils import ErrorList
            #     # print(item.errors.as_data())
            #     print(item.errors)
            #     # print(type(item.errors))
    return render(request, 'register.html', locals())
視圖函數
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
    <script src="/static/jquery-3.3.1.js"></script>
    <title>註冊</title>
</head>
<body>
<div class="row">
    <div class="col-md-6 col-md-offset-3">
        <form action="" method="post" novalidate>
            {% for foo in myform %}
                <p>{{ foo.label }}:{{ foo }} <span class="pull-right">{{ foo.errors.0 }}</span></p>
            {% endfor %}
            <input type="submit" value="提交"><span>{{error_all.0 }}</span>


        </form>
        <hr>

        <form action="" method="post" novalidate>
            <p>用戶名:{{ myform.name }} <span>{{ myform.errors.name }}</span></p>
            <p>用戶名:{{ myform.pwd }} <span>{{ myform.errors.pwd }}</span></p>
            <p>用戶名:{{ myform.email }} <span>{{ myform.errors.email }}</span></p>
            <input type="submit" value="提交">
        </form>


    </div>
</div>

</body>
</html>
模板
# 小結:

-forms組件的渲染錯誤信息 在模板中:<span>{{ foo.errors.0 }}</span>
-forms使用bootstrap樣式 widget=widgets.EmailInput(attrs={'class':'form-control'}))
-全局和局部鉤子函數 AOP:面向切面編程 -局部鉤子函數(再校驗name) def clean_name(self): # 從cleaned_data中取出字段的值 name = self.cleaned_data.get('name') # # 校驗是否以sb開頭 if name.startswith('sb'): raise ValidationError('不能以sb開頭') else: return name
-全局鉤子函數 def clean(self): pwd=self.cleaned_data.get('pwd') re_pwd=self.cleaned_data.get('re_pwd') if pwd==re_pwd: # 正確,返回self.cleaned_data return self.cleaned_data else: # 校驗失敗,拋異常 raise ValidationError('兩次密碼不一致')

 

2、cookie和session組件

  1.什麼是會話跟蹤

  咱們須要瞭解下什麼叫作會話,能夠把會話理解成客戶端和服務器之間的一次會晤,在一次會晤中可能會包含屢次請求和響應。例如你給10086打電話,你就是客戶端,10086就是服務器。雙方接通電話的那一刻起,會話就開始,到某一方掛斷電話表示會話結束,在通話過程當中,你會向10086 發出不少請求,那麼這個請求就在一個會話中。

在一個會話的多個請求中共享數據,這就是會話跟蹤技術。例如在一個會話中的請求以下:    

      請求銀行主頁; 

  • 請求登陸(請求參數是用戶名和密碼);
  • 請求轉帳(請求參數與轉帳相關的數據); 
  • 請求信譽卡還款(請求參數與還款相關的數據)。  

 

在這上會話中當前用戶信息必須在這個會話中共享的,由於登陸的是張三,那麼在轉帳和還款時必定是相對張三的轉帳和還款!這就說明咱們必須在一個會話過程當中有共享數據的能力。

  # 會話路徑技術使用cookie或session完成

咱們知道HTTP協議是無狀態協議,也就是說每一個請求都是獨立的!沒法記錄前一次請求的狀態。但HTTP協議中可使用Cookie來完成會話跟蹤!在Web開發中,使用session來完成會話跟蹤,session底層依賴Cookie技術。

  2.cookie

cookie的由來

你們都知道HTTP協議是無狀態的。

 

無狀態的意思是每次請求都是獨立的,它的執行狀況和結果與前面的請求和以後的請求都無直接關係,它不會受前面的請求響應狀況直接影響,也不會直接影響後面的請求響應狀況。

 

一句有意思的話來描述就是人生只如初見,對服務器來講,每次的請求都是全新的。

 

狀態能夠理解爲客戶端和服務器在某次會話中產生的數據,那無狀態的就覺得這些數據不會被保留。會話中產生的數據又是咱們須要保存的,也就是說要「保持狀態」。所以Cookie就是在這樣一個場景下誕生。

  # 什麼cookie

其實Cookie是key-value結構,相似於一個python中的字典。隨着服務器端的響應發送給客戶端瀏覽器。而後客戶端瀏覽器會把Cookie保存起來,當下一次再訪問服務器時把Cookie再發送給服務器。 Cookie是由服務器建立,而後經過響應發送給客戶端的一個鍵值對。客戶端會保存Cookie,並會標註出Cookie的來源(哪一個服務器的Cookie)。當客戶端向服務器發出請求時會把全部這個服務器Cookie包含在請求中發送給服務器,這樣服務器就能夠識別客戶端了!

  #cookie的原理

cookie的工做原理是:由服務器產生內容,瀏覽器收到請求後保存在本地,當瀏覽器再次訪問時,瀏覽器會自動帶上cookie,這樣服務器就能經過cookie的內容來判斷這個是誰了

  #cookie規範

cookie大小上限爲4kb;

一個服務器最多在瀏覽器上保存20個cookie

一個瀏覽器上最多保存300個cookie

上面的數據只是http的cookie規範,可是瀏覽器大戰的今天,一些瀏覽器爲了戰勝對手,爲了展示本身的能力起見,可能對cookie規範擴展了一些,例如每一個cookie大小爲8kb,最多能夠保存500個kb等,但也不會出現把你的硬盤佔滿的可能!

注意,不一樣的瀏覽器之間是不共享cookie的,也就是說在你使用IE訪問瀏覽器時,服務器會把Cookie發給IE,而後由IE保存起來,當你在使用FireFox訪問服務器時,不可能把IE保存的Cookie發送給服務器。

  #cookie的覆蓋

若是服務器發送重複大的cookie那麼會覆蓋原有的cookie,例如客戶端的第一個請求服務器端發送的cookie是:set-cookie:a=A;第二個請求服務器端發送的是:set-cookie:a=AA,那麼客戶端只留下一個cookie,即a=AA

  # 在瀏覽器中查看cookie

瀏覽器中按F12,點network--cookies就能看到

  

  django中操做cookie

  # 獲取cookie

request.COOKIES['key']
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)

參數:

  • default: 默認值
  • salt: 加密鹽
  • max_age: 後臺控制過時時間

  # 設置cookie

rep = HttpResponse(...)
rep = render(request, ...)

rep.set_cookie(key,value)
rep.set_signed_cookie(key,value,salt='加密鹽')

參數:

  • key, 鍵
  • value='', 值
  • max_age=None, 超時時間 cookie須要延續的時間(以秒爲單位)若是參數是\ None`` ,這個cookie會延續到瀏覽器關閉爲止
  • expires=None, 超時時間(IE requires expires, so set it if hasn't been already.)
  • path='/', Cookie生效的路徑,/ 表示根路徑,特殊的:根路徑的cookie能夠被任何url的頁面訪問,瀏覽器只會把cookie回傳給帶有該路徑的頁面,這樣能夠避免將cookie傳給站點中的其餘的應用。
  • domain=None, Cookie生效的域名 你可用這個參數來構造一個跨站cookie。如, domain=".example.com"所構造的cookie對下面這些站點都是可讀的:www.example.com 、 www2.example.com 和an.other.sub.domain.example.com 。若是該參數設置爲 None ,cookie只能由設置它的站點讀取
  • secure=False, 瀏覽器將經過HTTPS來回傳cookie
  • httponly=False 只能http協議傳輸,沒法被JavaScript獲取(不是絕對,底層抓包能夠獲取到也能夠被覆蓋)

  #刪除cookie

def logout(request):
    rep = redirect("/login/")
    rep.delete_cookie("user")  # 刪除用戶瀏覽器上以前設置的usercookie值
    return rep

  #cookie版登陸校驗

def login_auth(func):
    def inner(request,*args,**kwargs):
        next_url=request.get_full_path()
        if request.COOKIES.get('is_login'):
            return func(request,*args,**kwargs)
        else:
            return redirect('cookie_login/?next=%s'%next_url)
    return inner
@login_auth
def cookie_order(request):
    return HttpResponse('我是訂單頁面')
@login_auth
def cookie_index(request):
    name=request.COOKIES.get('username')
    return render(request,'cookie_index.html',{'name':name})
def cookie_login(request):
    if request.method =='POST':
        next_url=request.GET.get('next')
        name=request.POST.get('name')
        password=request.POST.get('password')
        if name == 'lqz' and password == '123':
            import datetime
            now=datetime.datetime.now().strftime('%Y-%m-%d %X')
            print(now)
            obj=redirect(next_url)
            obj.set_cookie('is_login',True)
            obj.set_cookie('username',name)
            obj.set_cookie('login_time',now)
            return obj

    return render(request, 'cookie_login.html')
登陸認證裝飾器

  3.session

  # session的由來

Cookie雖然在必定程度上解決了「保持狀態」的需求,可是因爲Cookie自己最大支持4096字節,以及Cookie自己保存在客戶端,可能被攔截或竊取,所以就須要有一種新的東西,它能支持更多的字節,而且他保存在服務器,有較高的安全性。這就是Session。

問題來了,基於HTTP協議的無狀態特徵,服務器根本就不知道訪問者是「誰」。那麼上述的Cookie就起到橋接的做用。

咱們能夠給每一個客戶端的Cookie分配一個惟一的id,這樣用戶在訪問時,經過Cookie,服務器就知道來的人是「誰」。而後咱們再根據不一樣的Cookie的id,在服務器上保存一段時間的私密資料,如「帳號密碼」等等。

總結而言:Cookie彌補了HTTP無狀態的不足,讓服務器知道來的人是「誰」;可是Cookie以文本的形式保存在本地,自身安全性較差;因此咱們就經過Cookie識別不一樣的用戶,對應的在Session裏保存私密的信息以及超過4096字節的文本。

另外,上述所說的Cookie和Session實際上是共通性的東西,不限於語言和框架。

  #django中的session相關方法

# 獲取、設置、刪除Session中數據
request.session['k1']
request.session.get('k1',None)
request.session['k1'] = 123
request.session.setdefault('k1',123) # 存在則不設置
del request.session['k1']


# 全部 鍵、值、鍵值對
request.session.keys()
request.session.values()
request.session.items()
request.session.iterkeys()
request.session.itervalues()
request.session.iteritems()

# 會話session的key
request.session.session_key

# 將全部Session失效日期小於當前日期的數據刪除
request.session.clear_expired()

# 檢查會話session的key在數據庫中是否存在
request.session.exists("session_key")

# 刪除當前會話的全部Session數據(只刪數據庫)
request.session.delete()
  
# 刪除當前的會話數據並刪除會話的Cookie(數據庫和cookie都刪)。
request.session.flush() 
    這用於確保前面的會話數據不能夠再次被用戶的瀏覽器訪問
    例如,django.contrib.auth.logout() 函數中就會調用它。

# 設置會話Session和Cookie的超時時間
request.session.set_expiry(value)
    * 若是value是個整數,session會在些秒數後失效。
    * 若是value是個datatime或timedelta,session就會在這個時間後失效。
    * 若是value是0,用戶關閉瀏覽器session就會失效。
    * 若是value是None,session會依賴全局session失效策略。

Django中使用session時,作的事:

# 生成隨機字符串
# 寫瀏覽器cookie -> session_id: 隨機字符串
# 寫到服務端session:
    # {
    #     "隨機字符串": {'user':'alex'}
    # }

  # django中的session配置

1. 數據庫Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默認)

2. 緩存Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
SESSION_CACHE_ALIAS = 'default'                            # 使用的緩存別名(默認內存緩存,也能夠是memcache),此處別名依賴緩存的設置

3. 文件Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
SESSION_FILE_PATH = None                                    # 緩存文件路徑,若是爲None,則使用tempfile模塊獲取一個臨時地址tempfile.gettempdir() 

4. 緩存+數據庫
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎

5. 加密Cookie Session
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎

其餘公用設置項:
SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串(默認)
SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路徑(默認)
SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默認)
SESSION_COOKIE_SECURE = False                            # 是否Https傳輸cookie(默認)
SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http傳輸(默認)
SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默認)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否關閉瀏覽器使得Session過時(默認)
SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次請求都保存Session,默認修改以後才保存(默認)

思考,若是第二人再次在同一個瀏覽器上登陸,django-session表會怎樣

  # CBV中加裝飾器

from django import views
from django.utils.decorators import method_decorator
# @method_decorator(login_auth,name='get')
# @method_decorator(login_auth,name='post')
class UserList(views.View):
    # @method_decorator(login_auth)
    def dispatch(self, request, *args, **kwargs):
        obj=super().dispatch(request, *args, **kwargs)
        return obj

    @method_decorator(login_auth)
    def get(self,request):
        return HttpResponse('我是用戶列表')

    def post(self,request):
        return HttpResponse('我是用戶列表')

 

3、auth組件

  1.Auth模塊是什麼

Auth模塊是Django自帶的用戶認證模塊:

咱們在開發一個網站的時候,無可避免的須要設計實現網站系統,此時咱們須要實現包括用戶註冊、用戶登陸、用戶認證、註銷、修改密碼等功能,這還真是個麻煩的事情

Django做爲一個完美主義者的終極框架,固然也會想到用戶的這些痛點。它內置了強大的用戶認證系統--auth,它默認使用 auth_user 表來存儲用戶數據。

  2.auth模塊經常使用方法

導入模塊

from django.contrib import auth

  #authenticate()

提供了用戶認證功能,即驗證用戶名以及密碼是否正確,通常須要username 、password兩個關鍵字參數。

若是認證成功(用戶名和密碼正確有效),便會返回一個 User 對象。

authenticate()會在該 User 對象上設置一個屬性來標識後端已經認證了該用戶,且該信息在後續的登陸過程當中是須要的。

用法:

user = authenticate(username='usernamer',password='password')

  #login(HttpRequest,user)

該函數接受一個HttpRequest對象,以及一個通過認證的User對象。

該函數實現一個用戶登陸的功能。它本質上會在後端爲該用戶生成相關session數據。

用法:

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:
    login(request, user)
    # Redirect to a success page.
    ...
  else:
    # Return an 'invalid login' error message.
    ...

  #logout(request)

該函數接受一個HttpRequest對象,無返回值

當調用該函數時,當前請求的session信息會所有清除,該用戶即便沒有登陸,使用該函數也不會報錯,

用法:

from django.contrib.auth import logout
   
def logout_view(request):
  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_requier()

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/'  # 這裏配置成你項目登陸頁面的路由

  #create_user()

auth提供一個建立新用戶的方法,須要提供必要參數(username、password)等

用法

from django.contrib.auth.models import User
user = User.objects.create_user(username='用戶名',password='密碼',email='郵箱',...)

  #create_superuser()

auth提供的一個建立的超級用戶的方法,須要提供必要的參數(username、password)等

用法

from django.contrib.auth.models import User
user = User.objects.create_superuser(username='用戶名',password='密碼',email='郵箱',...)

  #check_password(password)

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

密碼正確返回True,不然返回False。

用法:

ok = user.check_password('密碼')

Auth模塊

 

1 Auth模塊是什麼

Auth模塊是Django自帶的用戶認證模塊:

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

Django做爲一個完美主義者的終極框架,固然也會想到用戶的這些痛點。它內置了強大的用戶認證系統--auth,它默認使用 auth_user 表來存儲用戶數據。

2 auth模塊經常使用方法

from django.contrib import auth

authenticate()

提供了用戶認證功能,即驗證用戶名以及密碼是否正確,通常須要username 、password兩個關鍵字參數。

若是認證成功(用戶名和密碼正確有效),便會返回一個 User 對象。

authenticate()會在該 User 對象上設置一個屬性來標識後端已經認證了該用戶,且該信息在後續的登陸過程當中是須要的。

用法:

user = authenticate(username='usernamer',password='password')

login(HttpRequest, user)

該函數接受一個HttpRequest對象,以及一個通過認證的User對象。

該函數實現一個用戶登陸的功能。它本質上會在後端爲該用戶生成相關session數據。

用法:

複製代碼
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:
    login(request, user)
    # Redirect to a success page.
    ...
  else:
    # Return an 'invalid login' error message.
    ...
複製代碼

logout(request)

該函數接受一個HttpRequest對象,無返回值。

當調用該函數時,當前請求的session信息會所有清除。該用戶即便沒有登陸,使用該函數也不會報錯。

用法:

from django.contrib.auth import logout
   
def logout_view(request):
  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/'  # 這裏配置成你項目登陸頁面的路由

create_user()

auth 提供的一個建立新用戶的方法,須要提供必要參數(username、password)等。

用法:

from django.contrib.auth.models import User
user = User.objects.create_user(username='用戶名',password='密碼',email='郵箱',...)

create_superuser()

auth 提供的一個建立新的超級用戶的方法,須要提供必要參數(username、password)等。

用法:

from django.contrib.auth.models import User
user = User.objects.create_superuser(username='用戶名',password='密碼',email='郵箱',...)

check_password(password)

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

密碼正確返回True,不然返回False。

用法:

ok = user.check_password('密碼')

set_password(password)

auth 提供的一個修改密碼的方法,接收 要設置的新密碼 做爲參數。

注意:設置完必定要調用用戶對象的save方法!!!

用法:

user.set_password(password='')
user.save()
@login_required
def set_password(request):
    user = request.user
    err_msg = ''
    if request.method == 'POST':
        old_password = request.POST.get('old_password', '')
        new_password = request.POST.get('new_password', '')
        repeat_password = request.POST.get('repeat_password', '')
        # 檢查舊密碼是否正確
        if user.check_password(old_password):
            if not new_password:
                err_msg = '新密碼不能爲空'
            elif new_password != repeat_password:
                err_msg = '兩次密碼不一致'
            else:
                user.set_password(new_password)
                user.save()
                return redirect("/login/")
        else:
            err_msg = '原密碼輸入錯誤'
    content = {
        'err_msg': err_msg,
    }
    return render(request, 'set_password.html', content)
修改過的簡單事例

  #User對象屬性

User對象屬性:username, password

is_staff : 用戶是否擁有網站的管理權限.

is_active : 是否容許用戶登陸, 設置爲 False,能夠在不刪除用戶的前提下禁止用戶登陸。

  

  3.擴展默認的auth_user表

這內置的認證系統這麼好用,可是auth_user表字段都是固定的那幾個,我在項目中無法拿來直接使用啊!

好比,我想要加一個存儲用戶手機號的字段,怎麼辦?

聰明的你可能會想到新建另一張表而後經過一對一和內置的auth_user表關聯,這樣雖然能知足要求可是有沒有更好的實現方式呢?

答案是固然有了。

咱們能夠經過繼承內置的 AbstractUser 類,來定義一個本身的Model類。

這樣既能根據項目需求靈活的設計用戶表,又能使用Django強大的認證系統了。

from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
    """
    用戶信息表
    """
    nid = models.AutoField(primary_key=True)
    phone = models.CharField(max_length=11, null=True, unique=True)
    
    def __str__(self):
        return self.username

注意:

  按上面的方式擴展內置的auth_user表以後,必定要在settings.py中告訴Django,我如今使用我新定的User表來作用戶認證,寫法以下:

# 引用Django自帶的User表,繼承使用時須要設置
AUTH_USER_MODEL = "app名.UserInfo"

再次注意:

一旦咱們指定了新的認證系統所使用的表,咱們就須要從新在數據庫中建立該表,而不能繼續使用原來默認的auth_user表了

相關文章
相關標籤/搜索