Django详解之四、cookie和session

一、使用背景

思路
简单的后台管理:对人员的管理
1、	登录注册
2、	老师
班级管理
学院管理
3、	增删改查
开发:
1、	定义数据库表结构
a)	表结构关系
i.	class classes(models.Model):
1.	caption=models.Charfield(max_length=32)
class student(models.Model):
	name=models.CharField(max_length=32)
	cls=models.Foreignkey(‘classes’)

	username=models.CharFeild(max_length=32)
	password=models.CharFeild(max_length=32)
class Teacher(models.Model):
	name=models.Charfield(max_length=32)
	
	username=models.CharFeild(max_length=32)
	password=models.CharFeild(max_length=32)
	cls=models.ManytoMany(‘classes’)

第三张表

登录注册
		提交表单:
			-form
			-Ajax
		登录
			-成功:记住状态<->保持会话
			-失败:错误提示

依据上面思路来讲解cookie以及session

一、cookie

cookie:

1、  保存在用户浏览器

2、  可以主动清除

3、  也可以被“伪造”

4、  跨域是不共享的

5、  浏览器可以设置不接收cookie

6、  给cookie设置超时时间  max_age=””(秒)

cookie是什么?

就是保存在浏览器端的键值对,可以利用来做登录

下面是设置cookie和获取cookie的操作

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
from app01 import models
def login(request):
    message=''
    if request.method=='POST':
        user=request.POST.get('user')
        pwd=request.POST.get('pwd')
        if user=="a" and pwd=="a":
            #cookie
            req=redirect("/index.html")
            req.set_cookie("username",user)
            return req
        else:
            message = "用户名或者密码错误"
    return  render(request,'login.html',{"msg":message})
def index(request):
    #如果用户已经登录,获取当前登录的用户名
    #否则,返回登录页面
    username=request.COOKIES.get('username')
    print(username)
    if username:
        render(request, 'index.html', {"username": username})
    else:
        return redirect("/login.html")

下面例子:

首先写一个登录页面,然后用户登录就会跳转到页面, 谁登录的就会显示欢迎谁

根据MTV模式首先配置M

1、首先创建数据库表

from django.db import models

'''
这里创建四张表
一张班级
一张学生
一张教师,教师和班级之间的关系是多对多
一张管理员
'''

# Create your models here.
class Classes(models.Model):
    caption=models.CharField(max_length=32)

class Student(models.Model):
    name=models.CharField(max_length=32)
    cls=models.ForeignKey('Classes')

class Teacher(models.Model):
    name=models.CharField(max_length=32)
    cls=models.ManyToManyField('Classes')

class Administrator(models.Model):
    username=models.CharField(max_length=32)
    password=models.CharField(max_length=32)

2、配置连接mysql

在setings中配置:

# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#     }
# }
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'user_django',
        'USER':'root',
        'PASSWORD':'123456',
        'HOST':"",
        'PORT':'3306'
    }
}

然后配置app01

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01',
]

之后init文件中导入pymysql

import pymysql
pymysql.install_as_MySQLdb()

2、配置T

配置登录后的欢迎页面index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>
    hello {{ username }}
</h1>

</body>
</html>

以及用户登录页面login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="login.html" method="post">
    {% csrf_token %}     //这里是做csrf用的
    <div>
        <label for="user">用户名:</label>
        <input type="text" id="user" name="user"/>
    </div>
    <div>
        <label for="pwd">密  码: </label>
        <input type="password" name="pwd"/>
    </div>
    <div>
        <label></label>
        <input type="submit" value="登录"/>
        <span style="color: red">{{ msg }}</span>
    </div>
</form>

</body>
</html>

3、配置MTV中的V

首先配置urls

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r"^login.html$",views.login),
    url(r"^index.html$",views.index)
]

之后在配置view视图函数

 

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
from app01 import models
def login(request):
    # models.Administrator.objects.create(
    #     username="pyrene",
    #     password="pyrene"
    # )
    message=''
    if request.method=='POST':
        user=request.POST.get('user')
        pwd=request.POST.get('pwd')
        c=models.Administrator.objects.filter(username=user,password=pwd).count()
        if c:
            #cookie
            req=redirect("/index.html")
            req.set_cookie("username",user)
            return req
        else:
            message = "用户名或者密码错误"
    return  render(request,'login.html',{"msg":message})
def index(request):
    #如果用户已经登录,获取当前登录的用户名
    #否则,返回登录页面
    username=request.COOKIES.get('username')
    print(username)
    if username:
        return render(request, 'index.html', {"username": username})
    else:
        return redirect("/login.html")

往数据库中添加数据,然后连接http://127.0.0.1:8000/login.html,就把数据添加到数据库中,

之后注释掉添加的语句,直接利用cookie来判断用户是否登录

二、cookie中的参数

def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
               domain=None, secure=False, httponly=False):

max_age设置秒

path: 设置路径

         /  表示,全局生效

         /xxx/ 表示,只有当前url生效

domian:设置域名

         obj.set_cookie(“k”,”v”,domain=””)

假如这里domain=”pyrene.com”并且设置cookie为k1,v1

这个时候访问下面二级域名www.pyrene.com以及crn.pyrene.com 的时候下面的二级域名里面没有cookie就会去pyrene.com中寻找二级域名,也就能获取

如果domain=www.pyrene.com并且设置cookie为k2,v2

这个时候如果访问www.pyrene.com/pyrene 这样就能够获取cookie

但是如果要访问crn.pyrene.com 这样是获取不到cookie的

expires:也是设置超时时间的

obj.set_cookie(“k1”,”v1”)

v=datatime.datetime.utcnow()+datetime.timedelta(seconds=10)

obj.set_cookie(“k2”,”v2”,expires=v)

 

如:

def test(request):
    import datetime
    v=datetime.datetime.utcnow()+datetime.timedelta(seconds=10)
    obj=HttpResponse("ok")
    obj.set_cookie("k2","v1",expires=v)
    return obj
def xiaohu(request):
    v=request.COOKIES.get("k2")
    return HttpResponse(v)

url配置:

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r"^login.html$",views.login),
    url(r"^index.html$",views.index),
    url(r"^test.html$",views.test),
    url(r"^xiaohu.html$",views.xiaohu)
]

当用户访问test.html之后再访问xiaohu.html的时候就会获取到k2对应的值,但是当10秒钟过后这个值就会消失,那么xiaohu这个url页面就会显null

 

三、利用js来设置获取cookie

客户端浏览器操作cookie两种方式:

         dom操作  --》麻烦

         jquery插件               --》

                                               jquery.cookie.js

                                               jquery.js

参数 expires:不仅仅支持数字 10

也支持d=new Date()

d.setDate(d.getDate()+1)

例子:

首先在settings中加入静态文件配置

STATIC_URL = '/static/'
STATICFILES_DIRS=(
    os.path.join(BASE_DIR,"static"),
)
之后在static中引入两个文件

然后配置urls

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r"^login.html$",views.login),
    url(r"^index.html$",views.index),
    url(r"^test.html$",views.test),
    url(r"^xiaohu.html$",views.xiaohu),
    url(r"^js_cookie.html$",views.js_cookie)
]

在views中写入视图函数

def js_cookie(request):
    print(request.COOKIES)
    obj=render(request,"js_cookie.html")
    obj.set_cookie("k1","v1")
    return obj

然后在templates中写入js_cookie.js文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="/static/jquery-2.1.4.min.js"></script>
    <script src="/static/jquery.cookie.js"></script>
    <script>
        //$.cookie()
        //一个参数:$.cookie(k) 获取值
        //两个参数:$.cookie(k.v) 设置值
        $.cookie("k","v",{"path":"/index.html"})
    </script>
</head>
<body>

</body>
</html>

然后就可以在js_cookie.html进行操作cookie

语法:

$.cookie(“k”,”v”,{ “path”:”/xx”})

其中字典中是参数

 

总结:

为什么有cookie:

没有cookie会把后台信息暴露出来

cookie是放入到响应头里面的。

1、浏览器连接把cookie放入到请求头发送给服务器,2、服务器把cookie放入到响应头中发给浏览器中,3、浏览器把客户端中的cookie放入到请求头发给服务器

 

cookie的三个重要点:

1、  客户端可以设置

2、  服务端可以设置

3、  保存在客户端

 

cookie的应用:

         登录认证

=====================》不敏感cookie的方法

set_cookie,request.COOKIES.get()

普通cookie

         如果有敏感信息(直接看到)就不适合放入里面

签名cookie

set_signed_cookie   get_signed_cookie

签名(加密)cookie,敏感信息(可能会被解密)

如果有敏感信息就不要放入到上面的两种cookie中

=====================》如果有敏感cookie的时候就需要用下面方法

session

session是什么:

         session是服务器端的一个键值对

         session内部机制依赖于cookie

因为django中内部自己封装了session,所以直接可以用

设置session:

request.session[“is_login”]=true

获取session注意这里用小括号

is_login=request.session.get(“is_login”)

 

session流程:

第一次:用户访问服务器,服务器会把session随机字符串(request.session[‘is_login’]=False)以及前端页面返回给用户

第二次:用户把账户密码和session随机字符串发送给服务器,服务器收到之后对比成功就返回给客户端(request.session[‘is_login’]=True)

第三次:客户端跳转页面会连接服务器对比session,比对成功就正常跳转,没有就跳转到登录页面

下面是用户登录的例子:

index.html,登录后返回的页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>
    hello {{ username }}
</h1>

</body>
</html>

login.html登录页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="login.html" method="post">
    {% csrf_token %}
    <div>
        <label for="user">用户名:</label>
        <input type="text" id="user" name="user"/>
    </div>
    <div>
        <label for="pwd">密  码: </label>
        <input type="password" name="pwd"/>
    </div>
    <div>
        <label></label>
        <input type="submit" value="登录"/>
        <span style="color: red">{{ msg }}</span>
    </div>
</form>

</body>
</html>

后台views视图函数中的定义session登录

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
from app01 import models
def login(request):
    # models.Administrator.objects.create(
    #     username="pyrene",
    #     password="pyrene"
    # )
    message=''
    if request.method=='POST':
        user=request.POST.get('user')
        pwd=request.POST.get('pwd')
        c = models.Administrator.objects.filter(username=user, password=pwd).count()
        if c:
            request.session['is_login'] = True
            request.session["username"]=user
            rep = redirect('/index.html')
            return rep
        else:
            message = "用户名或者密码错误"
    return  render(request,'login.html',{"msg":message})

def index(request):
    is_login=request.session.get("is_login")
    if is_login:
        current_user=request.session.get("username")
        return render(request,"index.html",{"username":current_user})
    else:
        return redirect("/login.html")

注意这里设置了session就是在数据库中生成了session这张表,然后把定义的session等装到数据库中

这里的session内部原理和tornado的session原理是一样的,要想详细了解,请看tornado自定义session

 

如果出现下面这个错误,应该是写session的小括号写成了[],中括号是获取下标的

'method' object is not subscriptable

session使用一、

 

session基本操作使用
 
    def index(request):
        # 获取、设置、删除Session中数据
        request.session['k1']  获取值
        request.session.get('k1',None)  获取值,没有没空

        request.session['k1'] = 123   设置值。存不存在都设置成功
        request.session.setdefault('k1',123) # 存在则不设置

        del request.session['k1']  删除session
 
        # 所有 键、值、键值对
        request.session.keys()
        request.session.values()
        request.session.items()
        request.session.iterkeys()  迭代
        request.session.itervalues()
        request.session.iteritems()
 
 
        # 获取当前用户session的随机字符串
        request.session.session_key
 
        # 将所有Session失效日期小于当前日期的数据删除
        request.session.clear_expired()
 
        # 检查 用户session的随机字符串 在数据库中是否
        request.session.exists("session_key")
 
        # 删除当前用户的所有Session数据
        request.session.delete("session_key")
 
        request.session.set_expiry(value)
            * 如果value是个整数,session会在些秒数后失效。
            * 如果value是个datatime或timedelta,session就会在这个时间后失效。
            * 如果value是0,用户关闭浏览器session就会失效。
            * 如果value是None,session会依赖全局session失效策略。

实例:

用户访问页面然后点击注销之后就把session删除掉回到主页面

views操作

def logout(request):
    request.session.clear()
    return redirect("/login.html")

urls操作

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r"^login.html$",views.login),
    url(r"^index.html$",views.index),
    url(r"^logout.html",views.logout)

前端index页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>
    hello {{ username }}
</h1>
<a href="/logout.html">注销</a>
</body>
</html>

session使用二、

Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:

  • 数据库(默认)
  • 缓存
  • 文件
  • 缓存+数据库
  • 加密cookie
    • Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
    •  
    • a. 配置 settings.py
•	SESSION_ENGINE = 'django.contrib.sessions.backends.db'  # 引擎(默认)

SESSION_COOKIE_NAME = "sessionid"  # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)(通俗端说就是更改浏览器端session的名字)
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失效)
SESSION_SAVE_EVERY_REQUEST = False  # 是否每次请求都保存Session,默认修改之后才保存(默认)(每次请求来的时候更新不更新session中的值)
b. 使用
 
    def index(request):
        # 获取、设置、删除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的随机字符串
        request.session.session_key
 
        # 将所有Session失效日期小于当前日期的数据删除
        request.session.clear_expired()
 
        # 检查 用户session的随机字符串 在数据库中是否
        request.session.exists("session_key")
 
        # 删除当前用户的所有Session数据
        request.session.delete("session_key")
 
        request.session.set_expiry(value)
            * 如果value是个整数,session会在些秒数后失效。
            * 如果value是个datatime或timedelta,session就会在这个时间后失效。
            * 如果value是0,用户关闭浏览器session就会失效。
            * 如果value是None,session会依赖全局session失效策略。

  2、缓存Session

 

a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
    SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
 
 
    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,默认修改之后才保存
 
 
 
b. 使用
 
    同上

3、文件Session

a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
    SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()                                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T
 
 
    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,默认修改之后才保存
 
b. 使用
 
    同上

4、缓存+数据库Session

 

数据库用于做持久化,缓存用于提高效率
 
a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎
 
b. 使用
 
    同上

5、加密cookie Session

 

a. 配置 settings.py
     
    SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎
 
b. 使用
 
    同上

基于装饰器实现用户登录

对于登录之后才能访问的功能页面,用装饰器实现

类的话是继承,方法的话就是装饰器

总体代码:

要实现如下:

1、  把数据存储在数据库中

2、  创建老师页面,登录页面,教师页面,班级页面,index公有页面

3、  通过session操作,谁登录就显示谁

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
from app01 import models
def login(request):
    # models.Administrator.objects.create(
    #     username="pyrene",
    #     password="pyrene"
    # )
    message=''
    if request.method=='POST':
        user=request.POST.get('user')
        pwd=request.POST.get('pwd')
        c = models.Administrator.objects.filter(username=user, password=pwd).count()
        if c:
            request.session['is_login'] = True
            request.session["username"]=user
            rep = redirect('/index.html')
            return rep
        else:
            message = "用户名或者密码错误"
    return  render(request,'login.html',{"msg":message})

def logout(request):
    request.session.clear()
    return redirect("/login.html")


#由于index和handler_classes都是登录后的操作所以可以用装饰器实现
def auth(func):
    def inner(request,*args,**kwargs):
        is_login = request.session.get("is_login")
        if is_login:
            return func(request,*args,**kwargs)
        else:
            return redirect("/login.html")
    return inner
@auth
def index(request):
    current_user=request.session.get("username")
    return render(request,"index.html",{"username":current_user})

@auth
def handle_classes(request):
    current_user=request.session.get("username")
    return render(request,"index.html",{"username":current_user})

def handler_student(request):
    is_login=request.session.get("is_login")
    if is_login:
        current_user=request.session.get("username")
        return render(request,"student.html",{"username":current_user})
    else:
        return redirect("/login.html")

def handler_teacher(request):
    is_login=request.session.get("is_login")
    if is_login:
        current_user=request.session.get("username")
        return render(request,"teacher.html",{"username":current_user})
    else:
        return redirect("/login.html")
views代码

 

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r"^login.html$",views.login),
    url(r"^index.html$",views.index),
    url(r"^logout.html",views.logout),
    url(r"^classes.html",views.handle_classes),
    url(r"^teacher.html",views.handler_teacher),
    url(r"^student.html",views.handler_student)

    # url(r"^test.html$",views.test),
    # url(r"^xiaohu.html$",views.xiaohu),
    # url(r"^js_cookie.html$",views.js_cookie)
]
urls代码

 

from django.db import models

'''
这里创建四张表
一张班级
一张学生
一张教师,教师和班级之间的关系是多对多
一张管理员
'''

# Create your models here.
class Classes(models.Model):
    caption=models.CharField(max_length=32)

class Student(models.Model):
    name=models.CharField(max_length=32)
    cls=models.ForeignKey('Classes')

class Teacher(models.Model):
    name=models.CharField(max_length=32)
    cls=models.ManyToManyField('Classes')

class Administrator(models.Model):
    username=models.CharField(max_length=32)
    password=models.CharField(max_length=32)
models代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="login.html" method="post">
    {% csrf_token %}
    <div>
        <label for="user">用户名:</label>
        <input type="text" id="user" name="user"/>
    </div>
    <div>
        <label for="pwd">密  码: </label>
        <input type="password" name="pwd"/>
    </div>
    <div>
        <label></label>
        <input type="submit" value="登录"/>
        <span style="color: red">{{ msg }}</span>
    </div>
</form>

</body>
</html>
login.html

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>
    hello {{ username }}
</h1>
<a href="/logout.html">注销</a>
</body>
</html>
index公有页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>当前登录用户{{ username }}</h1>

<div>

</div>
</body>
</html>
classes.html

 

posted @ 2017-05-19 23:04  pi-pi-miao-miao  阅读(166)  评论(0编辑  收藏  举报