1. 程式人生 > 實用技巧 >django修身大法之九陽真經

django修身大法之九陽真經

cookie和session

HTTP被設計為”無態”,也就是俗稱“臉盲”。 這⼀次請求和下⼀次請求 之間沒有任
何狀態保持,我們無法根據請求的任何方面(IP地址,使用者代理等)來識別來自同⼀
⼈的連續請求。實現狀態保持的方式:在客戶端或伺服器端儲存與會話有關的資料
(客戶端與伺服器端的⼀次通訊,就是⼀次會話)

  • cookie
  • session

不同的請求者之間不會共享這些資料,cookie和session與請求者⼀⼀對應。

⼀、cookie

cookies 是瀏覽器為 Web 伺服器存的⼀小資訊。 每次瀏覽器從某個伺服器請求頁面時,都會自動帶上以前收到的cookie。cookie儲存在客戶端,安全性較差,注意不要儲存敏感資訊。典型應用:

  • 網站登入
  • 購物車

用法:

# 1.設定cookie
HttpResponse.set_cookie(key, value='', max_age=None, expires=None,
path='/', domain=None, secure=None, httponly=False)
引數:
 
    key: cookie的名稱(*)

    value: cookie的值,預設是空字元

    max_age:cookies的持續有效時間(以秒計),如果設定為 None,cookies 在
    瀏覽器關閉的時候就失效了。

    expires:cookies的過期時間,格式:"Wdy, DD-Mth-YY HH:MM:SS GMT" 如果
    設定這個引數,它將覆蓋max_age。

    path: cookie⽣效的路徑字首,瀏覽器只會把cookie回傳給帶有該路徑的⻚
    ⾯,這樣你可以避免將cookie傳給站點中的其他的應⽤。/ 表示根路徑,特殊的:根路徑的cookie可以被任何url的⻚⾯訪問
     domain: cookie⽣效的站點。你可⽤這個引數來構造⼀個跨站cookie。如,domain=".example.com" 所構造的
     cookie對下⾯這些站點都是可 讀的: www.example.com 、
    www2.example.com。
		如果該引數設定為None,cookie只能由設定它的站點讀取。
     secure: 如果設定為 True ,瀏覽器將通過HTTPS來回傳cookie。
     httponly: 僅http傳輸不能使⽤js獲取cookie
#同set_cookie,不同點在於設定salt,即加鹽,加密儲存cookie資料
HttpResponse.set_signed_cookie(key, value, salt='', max_age=None,
expires=None, path='/', domain=None, secure=None, httponly=False)
#2 獲取cookie
HttpRequest.COOKIES.get(key)
#獲取加“鹽”的cookie
HttpRequest.get_signed_cookie(key, default=RAISE_ERROR, salt='',
max_age=None)
# 3刪除cookie
HttpResponse.delete_cookie(key, path='/', domain=None)

⼆、session

cookie看似解決了HTTP(短連線、無狀態)的會話保持問題,但把全部使用者資料
儲存在客戶端,存在安全隱患,

於是session出現了。我們可以 把關於使用者的資料儲存在服務端,在客戶端cookie
里加⼀個sessionID(隨機字串)。其工作流程

(1)、當用戶來訪問服務端時,服務端會生成⼀個隨機字串;

(2)、當用戶登入成功後 把 {sessionID :隨機字串} 組織成鍵值對加到cookie裡發
送給使用者;

(3)、伺服器以傳送給客戶端 cookie中的隨機字串做鍵,使用者資訊做值,儲存使用者資訊;

(4)、再訪問服務時客戶端會帶上sessionid,伺服器根據sessionid來確認使用者是否
訪問過網站

2.1 cookie和session的區別與聯絡

  • 區別
    • session將資料儲存與伺服器端 cookie儲存在客戶端
    • cookie 儲存在客戶端,不安全,sess儲存在伺服器端,客戶端只存
      sesseionid,安全
    • cookie在客戶端儲存值有大小的限制,大約幾kb。session沒有限制
  • 聯絡
    • session 基於cookie

2.2 session配置

  1. 首先在settings.py中有如下配置(系統預設),
INSTALLED_APPS = [
 'django.contrib.sessions',
]
MIDDLEWARE = [
 'django.contrib.sessions.middleware.SessionMiddleware',
]
  1. 進行資料遷移,生成session使用的資料庫表

2.3 session操作

  • session設定
def doregister(request):
     username = request.POST.get('username')
     password = request.POST.get('password')
     email = request.POST.get('email')
     user = User()
     user.username = username
     user.password = md5(password.encode('utf8')).hexdigest()
     user.email = email
     user.save()
     # 設定session
     request.session['username'] = username
     return render(request,"common/notice.html",context={
     'code':1,
     'msg':'註冊成功',
     'url':'three:index',
     'wait':3
     })
  • session獲取
def index(request):
     # session獲取
     username = request.session.get('username')
     return render(request,'three/index.html',context=
    {'username':username})
  • session刪除
    • clear() 清空所有session 但是不會將session表中的資料刪除
    • flush() 清空所有 並刪除表中的資料
    • logout() 退出登入 清除所有 並刪除表中的資料
    • del req.session['key'] 刪除某⼀個session的值
def logout(request):
     request.session.flush()
     return redirect(reverse("three:index"))
  • session過期時間

    req.session.set_expiry(5)

分頁

1. Paginator 分頁器

Paginator用於分頁,但Paginator並不具體管理具體的頁的處理,而是使用Page
物件管理具體頁面

  • 建立分頁器物件

格式: Paginator(<query_set查詢集>,每頁顯示資料的條數)

  • 物件的屬性
    • count 分頁物件的個數
    • num_pages 總頁數
    • page_range 頁碼的列表
  • 方法
    • page(num) 返回page物件 如果給定的頁碼不存在 則丟擲異常

2. page 物件

page物件具體負責每頁的處理,包括每頁的資料,當前頁的頁碼,是否有上⼀頁
或下⼀頁等.

類別 名稱 說明
屬性 object_list 當前頁碼上的所有資料
屬性 number 當前頁碼值
屬性 paginator 返回Paginator的物件
方法 has_next 是否有下⼀頁
方法 has_previous 是否有上⼀頁
方法 has_other_pages 是否有上⼀頁 或者下⼀頁
方法 next_page_number 返回下⼀頁的頁碼
方法 previous_page_number 返回上⼀頁的頁碼
方法 len 返回當前頁資料的個數
  • 例項
#路由
url(r'^userlist/$',views.userlist,name='userlist'),
url(r'^userlist/(\d+)/$',views.userlist,name='userlist1'),

# views.py
def userlist(request,page=1):
     users = User.objects.all()
     # 例項化分⻚物件,⼀⻚兩條記錄
     pagination = Paginator(users,2)
     page = pagination.page(page) #某⼀⻚的分⻚物件
     return render(request,'userlist.html',context={
     'data':page.object_list, #當前⻚的資料(列表)
     'page_range':pagination.page_range,#⻚碼範圍
     'page':page
     })
#模板⽂件
{% load static %}
<!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">
    <!-- 上述3個meta標籤*必須*放在最前⾯,任何其他內容都*必須*跟隨其後! -
   ->
    <title>⽤戶列表</title>
    <!-- Bootstrap -->
    <link href="{% static 'bootstrap/css/bootstrap.min.css' %}"
          rel="stylesheet">
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="bs-example" data-example-id="bordered-table">
            <table class="table table-bordered">
                <thead>
                <tr>
                    <th>#</th>
                    <th>⽤戶名</th>
                    <th>密碼</th>
                    <th>年齡</th>
                </tr>
                </thead>
                <tbody>
                {% for user in data %}
                    <tr>
                        <th scope="row">{{ forloop.counter }}
                        </th>
                        <td>{{ user.username }}</td>
                        <td>{{ user.password }}</td>
                        <td>{{ user.age }}</td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</div>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-4"></div>
        <div class="col-md-5">
            <nav aria-label="Page navigation">
                <ul class="pagination">
                    {% if page.has_previous %}
                        <li>
                            <a href="{% url 'app:userlist1'
page.number|add:'-1' %}" aria-label="Previous">
 <span aria-hidden="true">&laquo;
</span>
                            </a>
                        </li>
                    {% else %}
                        <li class="disabled">
 <span href="{% url 'app:userlist1'
page.number|add:'-1' %}" aria-label="Previous">
 <span aria-hidden="true">&laquo;
</span>
 </span>
                        </li>
                    {% endif %}
                    {% for num in pagerange %}
                        {% ifequal num page.number %}
                            <li class="active"><a href="{% url
'app:userlist1' num %}">{{ num }}</a></li>
                        {% else %}
                            <li><a href="{% url 'app:userlist1'
num %}">{{ num }}</a></li>
                        {% endifequal %}
                    {% endfor %}
                    {% if page.has_next %}
                        <li>
                            <a href="{% url 'app:userlist1'
page.number|add:'1' %}" aria-label="Next">
 <span aria-hidden="true">&raquo;
</span>
                            </a>
                        </li>
                    {% else %}
                        <li class="disabled">
 <span href="#" aria-label="Next">
 <span aria-hidden="true">&raquo;
</span>
 </span>
                        </li>
                    {% endif %}
                </ul>
            </nav>
        </div>
        <div class="col-md-3"></div>
    </div>
</div>
<!-- jQuery (Bootstrap 的所有 JavaScript 外掛都依賴 jQuery,所以必
須放在前邊) -->
<script src="{% static 'bootstrap/js/jquery-1.12.4.min.js' %}">
</script>
<!-- 載入 Bootstrap 的所有 JavaScript 外掛。你也可以根據需要只加載單
個外掛。 -->
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}">
</script>
</body>
</html>