文章对应的B站视频:https://www.bilibili.com/video/BV1Tu41127Ca/

Django系列文章对应的目录:https://www.cnblogs.com/emanlee/p/15860241.html

 

 

Django cookie 与 session

Cookie 是存储在客户端计算机上的文本文件,并保留了各种跟踪信息。

识别返回用户包括三个步骤:

服务器脚本向浏览器发送一组 Cookie。例如:姓名、年龄或识别号码等。

浏览器将这些信息存储在本地计算机上,以备将来使用。

当下一次浏览器向 Web 服务器发送任何请求时,浏览器会把这些 Cookie 信息发送到服务器,服务器将使用这些信息来识别用户。

HTTP 是一种"无状态"协议,这意味着每次客户端检索网页时,客户端打开一个单独的连接到 Web 服务器,服务器会自动不保留之前客户端请求的任何记录。

但是仍然有以下三种方式来维持 Web 客户端和 Web 服务器之间的 session 会话:

Cookies

一个 Web 服务器可以分配一个唯一的 session 会话 ID 作为每个 Web 客户端的 cookie,对于客户端的后续请求可以使用接收到的 cookie 来识别。

在Web开发中,使用 session 来完成会话跟踪,session 底层依赖 Cookie 技术。

Django 中 Cookie 的语法

设置 cookie:

rep.set_cookie(key,value,...)

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

获取 cookie:

request.COOKIES.get(key)

删除 cookie:

rep =HttpResponse || render || redirect

rep.delete_cookie(key)

 

 

创建应用和模型

settings.py

INSTALLED_APPS = [

'django.contrib.admin',

'django.contrib.auth',

'django.contrib.contenttypes',

'django.contrib.sessions',

'django.contrib.messages',

'django.contrib.staticfiles',

'app02', # 添加此项

]

MIDDLEWARE = [

'django.middleware.security.SecurityMiddleware',

'django.contrib.sessions.middleware.SessionMiddleware',

'django.middleware.common.CommonMiddleware',

#'django.middleware.csrf.CsrfViewMiddleware', # 此项

'django.contrib.auth.middleware.AuthenticationMiddleware',

'django.contrib.messages.middleware.MessageMiddleware',

'django.middleware.clickjacking.XFrameOptionsMiddleware',

]

import os

TEMPLATES = [

{

'BACKEND': 'django.template.backends.django.DjangoTemplates',

'DIRS': [os.path.join(BASE_DIR, 'app02')], # 此项

'APP_DIRS': True,

'OPTIONS': {

'context_processors': [

'django.template.context_processors.debug',

'django.template.context_processors.request',

'django.contrib.auth.context_processors.auth',

'django.contrib.messages.context_processors.messages',

],

},

},

]

DATABASES = {

'default':

{

'ENGINE': 'django.db.backends.mysql', # 数据库引擎

'NAME': 'mydb', # 数据库名称

'HOST': '127.0.0.1', # 数据库地址,本机 ip 地址 127.0.0.1

'PORT': 3306, # 端口

'USER': 'root', # 数据库用户名

'PASSWORD': '123456', # 数据库密码

}

}

# 在与 settings.py 同级目录下的 __init__.py 中引入模块和进行配置 (D:\temp-test\djangodemo\app02\app02\__init__.py)

import pymysql

pymysql.install_as_MySQLdb()

 

models.py

from django.db import models

class UserInfo(models.Model):

username = models.CharField(max_length=32)

password = models.CharField(max_length=64)

 

在命令行执行以下:

D:\temp-test\djangodemo\app02>python manage.py migrate

D:\temp-test\djangodemo\app02>python manage.py makemigrations app02

D:\temp-test\djangodemo\app02>python manage.py migrate app02

D:\temp-test\djangodemo\app02>

D:\temp-test\djangodemo\app02>python manage.py migrate

Operations to perform:

Apply all migrations: admin, app02, auth, contenttypes, sessions

Running migrations:

No migrations to apply.

Your models in app(s): 'app02' have changes that are not yet reflected in a migration, and so won't be applied.

Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.

D:\temp-test\djangodemo\app02>python manage.py makemigrations app02

Migrations for 'app02':

app02\migrations\0002_userinfo.py

- Create model UserInfo

D:\temp-test\djangodemo\app02>python manage.py migrate app02

Operations to perform:

Apply all migrations: app02

Running migrations:

Applying app02.0002_userinfo... OK

D:\temp-test\djangodemo\app02>

通过SQLyog 或 Navicat 添加一条记录:

 

 

 

urls.py

from django.contrib import admin

from django.urls import path

from . import views

urlpatterns = [

path('admin/', admin.site.urls),

path('login/', views.login),

path('index/', views.index),

path('logout/', views.logout),

path('order/', views.order)

]

 

views.py

from django.shortcuts import render, HttpResponse, redirect

from app02 import models

def login(request):

if request.method == "GET": ## get

return render(request, "login.html")

username = request.POST.get("username") ## post

password = request.POST.get("pwd")

user_obj = models.UserInfo.objects.filter(username=username, password=password).first()

print(user_obj.username)

if not user_obj: ## 用户名或密码不正确

return redirect("/login/") # 转向登录

else: ## 用户名或密码正确

rep = redirect("/index/") ## 转向index

rep.set_cookie("is_login", True) ## 设置cookie, "is_login", True

return rep

def index(request):

print(request.COOKIES.get('is_login')) # 获得cookie is_login

status = request.COOKIES.get('is_login') # 收到浏览器的再次请求,判断浏览器携带的cookie是不是登录成功的时候响应的 cookie

if not status: ## 若 cookie is_login 为空

return redirect('/login/')

return render(request, "index.html") ## 若 cookie is_login 不为空

def logout(request):

rep = redirect('/login/')

rep.delete_cookie("is_login") ## 删除 cookie is_login

return rep # 点击注销后执行,删除cookie,不再保存用户状态,并弹到登录页面

def order(request):

print(request.COOKIES.get('is_login'))

status = request.COOKIES.get('is_login')

if not status: ## 若 cookie is_login 为空

return redirect('/login/')

return render(request, "order.html")

 

以下创建三个模板文件:login.html、index.html、order.html。

login.html

Title

用户登录

{% csrf_token %}

用户名:

密码:

 

index.html

Title

index 页面。。。

注销

 

order.html

Title

order 页面。。。

注销

 

在Firefox里面运行,开启调试器:

 

 

 

 

 

 

 

运行结果如下图所示:

 

填写用户名和密码,点击提交查询:

 

 点击 注销:

 

 

 

 

 

 

Session(保存在服务端的键值对)

服务器在运行时可以为每一个用户的浏览器创建一个其独享的 session 对象,由于 session 为用户浏览器独享,所以用户在访问服务器的 web 资源时,可以把各自的数据放在各自的 session 中,当用户再去访问该服务器中的其它 web 资源时,其它 web 资源再从用户各自的 session 中取出数据为用户服务。

工作原理

a. 浏览器第一次请求获取登录页面 login。

b. 浏览器输入账号密码第二次请求,若输入正确,服务器响应浏览器一个 index 页面和一个键为 sessionid,值为随机字符串的 cookie,即 set_cookie ("sessionid",随机字符串)。

c. 服务器内部在 django.session 表中记录一条数据。

django.session 表中有三个字段。

session_key:存的是随机字符串,即响应给浏览器的 cookie 的 sessionid 键对应的值。

session_data:存的是用户的信息,即多个 request.session["key"]=value,且是密文。

expire_date:存的是该条记录的过期时间(默认14天)

d. 浏览器第三次请求其他资源时,携带 cookie :{sessionid:随机字符串},服务器从 django.session 表中根据该随机字符串取出该用户的数据,供其使用(即保存状态)。

注意: django.session 表中保存的是浏览器的信息,而不是每一个用户的信息。 因此, 同一浏览器多个用户请求只保存一条记录(后面覆盖前面),多个浏览器请求才保存多条记录。

cookie 弥补了 http 无状态的不足,让服务器知道来的人是"谁",但是 cookie 以文本的形式保存在浏览器端,安全性较差,且最大只支持 4096 字节,所以只通过 cookie 识别不同的用户,然后,在对应的 session 里保存私密的信息以及超过 4096 字节的文本。

session 设置:

request.session["key"] = value

执行步骤:

a. 生成随机字符串

b. 把随机字符串和设置的键值对保存到 django_session 表的 session_key 和 session_data 里

c. 设置 cookie:set_cookie("sessionid",随机字符串) 响应给浏览器

session 获取:

request.session.get('key')

执行步骤:

a. 从 cookie 中获取 sessionid 键的值,即随机字符串。

b. 根据随机字符串从 django_session 表过滤出记录。

c. 取出 session_data 字段的数据。

session 删除,删除整条记录(包括 session_key、session_data、expire_date 三个字段):

request.session.flush()

删除 session_data 里的其中一组键值对:

del request.session["key"]

执行步骤:

a. 从 cookie 中获取 sessionid 键的值,即随机字符串

b. 根据随机字符串从 django_session 表过滤出记录

c. 删除过滤出来的记录

实例

 

 

 

 

创建路由:

urls.py

from django.contrib import admin

from django.urls import path

from . import views

urlpatterns = [

path('admin/', admin.site.urls),

path('login/', views.login),

path('index/', views.index),

path('logout/', views.logout),

path('order/', views.order),

path('session_login/', views.s_login),

path('s_index/', views.s_index),

path('s_logout/', views.s_logout),

]

 

创建视图函数:

 

views.py

from django.shortcuts import render, HttpResponse, redirect

from app02 import models

def login(request):

if request.method == "GET":

return render(request, "login.html")

username = request.POST.get("username")

password = request.POST.get("pwd")

user_obj = models.UserInfo.objects.filter(username=username, password=password).first()

print(user_obj.username)

if not user_obj:

return redirect("/login/")

else:

rep = redirect("/index/")

rep.set_cookie("is_login", True)

return rep

def index(request):

print(request.COOKIES.get('is_login'))

status = request.COOKIES.get('is_login') # 收到浏览器的再次请求,判断浏览器携带的cookie是不是登录成功的时候响应的 cookie

if not status:

return redirect('/login/')

return render(request, "index.html")

def logout(request):

rep = redirect('/login/')

rep.delete_cookie("is_login")

return rep # 点击注销后执行,删除cookie,不再保存用户状态,并弹到登录页面

def order(request):

print(request.COOKIES.get('is_login'))

status = request.COOKIES.get('is_login')

if not status:

return redirect('/login/')

return render(request, "order.html")

###########################################################

def s_login(request):

if request.method == "GET":

return render(request, "login.html")

username = request.POST.get("username")

password = request.POST.get("pwd")

user_obj = models.UserInfo.objects.filter(username=username, password=password).first()

print(user_obj.username)

if not user_obj:

return redirect("/session_login/")

else:

request.session['is_login'] = True

request.session['user1'] = username

return redirect("/s_index/")

def s_index(request):

status = request.session.get('is_login')

if not status:

return redirect('/session_login/')

return render(request, "s_index.html")

def s_logout(request):

# del request.session["is_login"] # 删除session_data里的一组键值对

request.session.flush() # 删除一条记录包括(session_key session_data expire_date)三个字段

return redirect('/session_login/

 

 

模板文件:

s_index.html

Title

session_index 页面。。。{{ request.session.user1 }}

注销

 

运行结果如下图所示:

127.0.0.1:8003/session_login/

输入用户名和密码,提交查询:

 

 提交查询之后,可以看到有session

 

 注销之后,session没有了。

 

 

 

 

 

 

https://www.runoob.com/django/django-cookie-session.html

 

查看原文