内外端交互分页突显,Session和自定义分页

By admin in 4858.com on 2019年4月23日

 Cookie和Session

Django中操作Cookie

 

session开首介绍

session:汉语时不时翻译为‘会话’,其自然的意思是指有始有终的一多种动作,

就比方大家打电话一贯到挂断电话那那中档的一多元进程可以称作为1个session,

偶尔大家会听到会话1词,那里的对话就指的是其本意,也便是一个浏览器打开

到关闭的1整个之间。

当session与互联网协议相关联时,就会波及到面向连接和、或保持状态,

“面向连接”指的是在通讯从前要先创设3个通讯的水渠,比方大家拿起电话开首给多方

拨电话,直到对方接领悟后通讯才开始,不过写信对发件人来讲发出去的时候就应经伊始

通讯,,可是并无法分明收信人的地址是不是绝对正确,“保持状态”指的是通讯的1放可以把

消息关联起来,使得新闻之间能相互正视

Cookie

获取Cookie

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

参数:

  • default: 默认值
  • salt: 加密盐
  • max_age: 后台调控过期时间

本文转发自qimi博客,cnblog.liwenzhou.com

理解session机制

session机制是一种服务器端的编写制定,服务器使用一种恍若于散列表的布局(也可能正是选择散列表)

来保存音讯。

当程式必要为有个别客户端的呼吁成立八个session的时候,服务器首先检查这一个客户端的伸手里是或不是已包蕴了一个session标志

  • 号称session id,假使已盈盈几个session
    id则表明以前已为此客户端创立过session,服务器就根据session
    id把那一个session检索出来使用(如若寻觅不到,恐怕会新建三个),假使客户端请求不分包session
    id,则为此客户端创立3个session并且生成二个和此session相关联的session
    id,session
    id的值应该是3个不可能再度的唯一值,并且保留在一个近似于Map的会见中,session
    id将被在此次响应中回到给客户端保存。

  保存那些session
id的主意能使用cookie,那样在竞相进度中浏览器能自动的根据规则把那几个标志发挥给服务器。一般那个cookie的名字都以相仿于SEEESIONID,而。比方weblogic对于web应用软件生成的cookie,JSESSIONID=ByOK叁vjFD75aPnrF七C二HmdnV陆QZcEbzWoWiBYEnLerjQ9玖zWpBng!-14578876四,他的名字就是JSESSIONID。

  由于cookie能被人工的查禁,必须有任何机制以便在cookie被取缔时照旧能够把session
id传递回服务器。*日常被应用的1种工夫叫做UHavalL重写,便是把session
id直接附加在URubiconL路线的后边,附加措施也有三种,壹种是当做URubiconL路线的叠加消息,表现方式为http://…../xxx;jsessionid=ByOK …
99zWpBng!-14578876肆另壹种是作为查询字符串附加在UEscortL前面,表现形式为http://…../xxx?jsessionid=ByOK … 99zWpBng!-145788764 
那三种方法对于用户来讲是尚未差其他,只是服务器在分析的时候管理的不2法门分歧,采取第贰种方式也便于把session
id的音信和常规程式参数区分开来*。

Cookie的由来

世家都精通HTTP协议是无状态的。

无状态的意思是每回请求都以独立的,它的履市场价格况和结果与前方的请求和现在的请求都无一贯关联,它不会受前边的央求响应意况向来影响,也不会间接影响前边的呼吁响应情况。

一句有意思的话来讲述正是人生只如初见,对服务器来讲,每一回的请求都以斩新的。

意况能够清楚为客户端和服务器在某次会话中产生的多寡,那无状态的就以为那个多少不会被封存。会话中发生的数量又是大家须要保留的,也正是说要“保持状态”。因而Cookie就是在这么一个现象下诞生。

设置Cookie

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

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

内外端交互分页突显,Session和自定义分页。参数:

  • key, 键
  • value=”, 值
  • max_age=None, 超时时间
  • expires=None, 超时时间(IE requires expires, so set it if hasn’t been
    already.)
  • path=’/’, Cookie生效的路线,/
    表示根路线,特殊的:根路线的cookie能够被别的url的页面访问
  • domain=None, Cookie生效的域名
  • secure=False, https传输
  • httponly=False
    只好http协议传输,不能被JavaScript获取(不是纯属,底层抓包能够获得到也能够被覆盖)

概要:

5种session类型

Django中默许援救session,其里面提供了伍种档案的次序的session供开采者使用

数据库(默认)

缓存

文件

缓存+数据库

加密cookie

什么是Cookie

Cookie具体指的是壹段小新闻,它是服务器发送出来存款和储蓄在浏览器上的一组组键值对,下次拜会服务器时浏览器会自行教导那一个键值对,以便服务器提取有用音信。

删除Cookie

def logout(request):
    rep = redirect("/login/")
    rep.delete_cookie("user")  # 删除用户浏览器上之前设置的usercookie值
    return rep

Cookie版登录校验

4858.com 1

4858.com 2

def check_login(func):
    @wraps(func)
    def inner(request, *args, **kwargs):
        next_url = request.get_full_path()
        if request.get_signed_cookie("login", salt="SSS", default=None) == "yes":
            # 已经登录的用户...
            return func(request, *args, **kwargs)
        else:
            # 没有登录的用户,跳转刚到登录页面
            return redirect("/login/?next={}".format(next_url))
    return inner


def login(request):
    if request.method == "POST":
        username = request.POST.get("username")
        passwd = request.POST.get("password")
        if username == "xxx" and passwd == "dashabi":
            next_url = request.GET.get("next")
            if next_url and next_url != "/logout/":
                response = redirect(next_url)
            else:
                response = redirect("/class_list/")
            response.set_signed_cookie("login", "yes", salt="SSS")
            return response
    return render(request, "login.html")

4858.com 3

大家的cookie是保留在浏览器中的键值对

session具体操作

缓存session

SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置

文件session

SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() 

缓存+数据库

SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎

加密cookie session

SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎

Cookie的原理

Cookie的做事原理是:由服务器产生内容,浏览器收到请求后保存在当地;当浏览器再度访问时,浏览器会自动带上库克ie,那样服务器就能透过Cookie的情节来剖断那个是“什么人”了。

Session

Django中暗许协助Session,在那之中间提供了5种档案的次序的Session供开辟者使用:

  • 数据库(默认)
  • 缓存
  • 文件
  • 缓存+数据库
  • 加密cookie

缘何要有cookie?

公用项设置

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,默认修改之后才保存(默认)

  

举例

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()

    request.session.set_expiry(value)
        * 如果value是个整数,session会在些秒数后失效。
        * 如果value是个datatime或timedelta,session就会在这个时间后失效。
        * 如果value是0,用户关闭浏览器session就会失效。
        * 如果value是None,session会依赖全局session失效策略。

查看Cookie

我们采纳Chrome浏览器,展开开荒者工具。

4858.com 4

数据库Session

SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)

大家在造访浏览器的时候,千万民用访问同一个页面,我们只要拿着url地址就足以张开页面,可是因为大家的用户是差异等的,大家的权杖也差异等,就接近于大家的管理权限,每一个人有投机不一致的

 session版登6验证 

from functools import wraps


def check_login(func):
    @wraps(func)
    def inner(request, *args, **kwargs):
        next_url = request.get_full_path()
        if request.session.get("user"):
            return func(request, *args, **kwargs)
        else:
            return redirect("/login/?next={}".format(next_url))
    return inner


def login(request):
    if request.method == "POST":
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")

        if user == "alex" and pwd == "alex1234":
            # 设置session
            request.session["user"] = user
            # 获取跳到登陆页面之前的URL
            next_url = request.GET.get("next")
            # 如果有,就跳转回登陆之前的URL
            if next_url:
                return redirect(next_url)
            # 否则默认跳转到index页面
            else:
                return redirect("/index/")
    return render(request, "login.html")


@check_login
def logout(request):
    # 删除所有当前请求相关的session
    request.session.delete()
    return redirect("/login/")


@check_login
def index(request):
    current_user = request.session.get("user", None)
    return render(request, "index.html", {"user": current_user})

  

Django中操作Cookie

缓存Session

SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置

大家的浏览器在走访的时候会助长cookie,它就一定于三个标签,大家的各种人走访同一个网页的时候

CBV中加装饰器

CBV落成的记名视图

class LoginView(View):

    def get(self, request):
        """
        处理GET请求
        """
        return render(request, 'login.html')

    def post(self, request):
        """
        处理POST请求 
        """
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        if user == 'alex' and pwd == "alex1234":
            next_url = request.GET.get("next")
            # 生成随机字符串
            # 写浏览器cookie -> session_id: 随机字符串
            # 写到服务端session:
            # {
            #     "随机字符串": {'user':'alex'}
            # }
            request.session['user'] = user
            if next_url:
                return redirect(next_url)
            else:
                return redirect('/index/')
        return render(request, 'login.html')

 

要在CBV视图中运用大家地点的check_login装饰器,有以下二种方法:

from django.utils.decorators import method_decorator

1. 加在CBV视图的get或post方法上

4858.com 5

from django.utils.decorators import method_decorator


class HomeView(View):

    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    @method_decorator(check_login)
    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

4858.com 6

2. 加在dispatch方法上

4858.com 7

from django.utils.decorators import method_decorator


class HomeView(View):

    @method_decorator(check_login)
    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

4858.com 8

因为CBV中第二实施的正是dispatch方法,所以那样写一定于给get和post方法都丰硕了登入校验。

三. 一贯加在视图类上,但method_decorator必须传 name 关键字参数

若果get方法和post方法都急需登入校验的话就写多少个装饰器。

4858.com 9

from django.utils.decorators import method_decorator

@method_decorator(check_login, name="get")
@method_decorator(check_login, name="post")
class HomeView(View):

    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

4858.com 10

获取Cookie

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

参数:

  • default: 默认值
  • salt: 加密盐
  • max_age: 后台调节过期时间

文件Session

SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() 

会自带一些音讯,让浏览器去辨别用户的一定消息,从而把该用户的音讯再次回到给浏览器页面,

补充

CS途睿欧F Token相关装饰器在CBV只可以加到dispatch方法上

备注:

  • csrf_protect,为当下函数强制安装防跨站请求伪形成效,即使settings中从未安装全局中间件。
  • csrf_exempt,裁撤当前函数防跨站请求伪形成效,即使settings中安装了大局中间件。

4858.com 11

from django.views.decorators.csrf import csrf_exempt, csrf_protect


class HomeView(View):

    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

 

 

设置Cookie

Django中设置Cookie:(针对的是响应对象)

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

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

参数:

  • key, 键
  • value=”, 值
  • max_age=None, 超时时间
  • expires=None, 超时时间(IE requires expires, so set it if hasn’t been
    already.)
  • path=’/’, 库克ie生效的门路,/
    表示根路线,特殊的:根路线的cookie能够被别的url的页面访问
  • domain=None, Cookie生效的域名
  • secure=False, https传输
  • httponly=False
    只可以http协议传输,不恐怕被JavaScript获取(不是相对,底层抓包能够获得到也足以被掩盖)

缓存+数据库

SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎

纵然在我们的浏览器1来三回的进度中得以达成的,这么些cookie里面包涵的正是大家的独特消息,用以彼此区分,cookie里面包车型的士消息是以键对值的主意保留的,大家的cookie里面这么些键对值的章程保存下去的音讯是有时效性的,自定义设定期间

删除Cookie

def logout(request):
    rep = redirect("/login/")
    rep.delete_cookie("user")  # 删除用户浏览器上之前设置的usercookie值
    return rep

加密Cookie Session

SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎

其它公用设置项:

4858.com 12

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,默认修改之后才保存(默认)

4858.com 13

任凭你怎么设置Session,使用办法都一致:

4858.com 14

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()

    request.session.set_expiry(value)
        * 如果value是个整数,session会在些秒数后失效。
        * 如果value是个datatime或timedelta,session就会在这个时间后失效。
        * 如果value是0,用户关闭浏览器session就会失效。
        * 如果value是None,session会依赖全局session失效策略。

4858.com 15

Session版登入验证

4858.com 16

4858.com 17

from functools import wraps


def check_login(func):
    @wraps(func)
    def inner(request, *args, **kwargs):
        next_url = request.get_full_path()
        if request.session.get("user"):
            return func(request, *args, **kwargs)
        else:
            return redirect("/login/?next={}".format(next_url))
    return inner


def login(request):
    if request.method == "POST":
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")

        if user == "alex" and pwd == "alex1234":
            # 设置session
            request.session["user"] = user
            # 获取跳到登陆页面之前的URL
            next_url = request.GET.get("next")
            # 如果有,就跳转回登陆之前的URL
            if next_url:
                return redirect(next_url)
            # 否则默认跳转到index页面
            else:
                return redirect("/index/")
    return render(request, "login.html")


@check_login
def logout(request):
    # 删除所有当前请求相关的session
    request.session.delete()
    return redirect("/login/")


@check_login
def index(request):
    current_user = request.session.get("user", None)
    return render(request, "index.html", {"user": current_user})

4858.com 18

 

Session

CBV中加装饰器相关

CBV实现的登入视图

4858.com 19

class LoginView(View):

    def get(self, request):
        """
        处理GET请求
        """
        return render(request, 'login.html')

    def post(self, request):
        """
        处理POST请求 
        """
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        if user == 'alex' and pwd == "alex1234":
            next_url = request.GET.get("next")
            # 生成随机字符串
            # 写浏览器cookie -> session_id: 随机字符串
            # 写到服务端session:
            # {
            #     "随机字符串": {'user':'alex'}
            # }
            request.session['user'] = user
            if next_url:
                return redirect(next_url)
            else:
                return redirect('/index/')
        return render(request, 'login.html')

4858.com 20

要在CBV视图中选取大家地点的check_login装饰器,有以下两种格局:

from django.utils.decorators import method_decorator

1. 加在CBV视图的get或post方法上

4858.com 21

from django.utils.decorators import method_decorator


class HomeView(View):

    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    @method_decorator(check_login)
    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

4858.com 22

2. 加在dispatch方法上

4858.com 23

from django.utils.decorators import method_decorator


class HomeView(View):

    @method_decorator(check_login)
    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

4858.com 24

因为CBV中率先实行的正是dispatch方法,所以那样写一定于给get和post方法都加上了登陆校验。

3. 直接加在视图类上,但method_decorator必须传 name 关键字参数

设若get方法和post方法都亟需登入校验的话就写五个装饰器。

4858.com 25

from django.utils.decorators import method_decorator

@method_decorator(check_login, name="get")
@method_decorator(check_login, name="post")
class HomeView(View):

    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

4858.com 26

cookie应用的地点:

Session的由来

Cookie就算在自然水准上化解了“保持状态”的供给,可是由于Cookie自身最大支撑40九陆字节,以及库克ie本中国人民保险公司留在客户端,只怕被拦住或窃取,因而就要求有一种新的东西,它能支撑越多的字节,并且她保存在服务器,有较高的安全性。那便是Session。

标题来了,基于HTTP协议的无状态特征,服务器根本就不知道访问者是“何人”。那么上述的Cookie就起到桥接的服从。

我们能够给种种客户端的Cookie分配1个唯一的id,这样用户在走访时,通过Cookie,服务器就精晓来的人是“什么人”。然后大家再依靠分化的Cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等。

小结来讲:Cookie弥补了HTTP无状态的供不应求,让服务器知道来的人是“什么人”;然而Cookie以文件的样式保留在地头,本人安全性较差;所以大家就经过库克ie识别不一致的用户,对应的在Session里保存私密的音讯以及超越40玖6字节的公文。

此外,上述所说的库克ie和Session其实是共通性的事物,不限于语言和框架。

Session保存在服务端的键值对

补充

CSSportageF Token相关装饰器在CBV只可以加到dispatch方法上

备注:

  • csrf_protect,为日前函数强制安装防跨站请求伪造功能,即使settings中并未有安装全局中间件。
  • csrf_exempt,撤销当前函数防跨站请求伪造作用,就算settings中设置了大局中间件。

4858.com 27

from django.views.decorators.csrf import csrf_exempt, csrf_protect


class HomeView(View):

    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

4858.com 28

登录

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。
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失效策略。

自定义分页

4858.com 29

4858.com 30

data = []

for i in range(1, 302):
    tmp = {"id": i, "name": "alex-{}".format(i)}
    data.append(tmp)

print(data)


def user_list(request):

    # user_list = data[0:10]
    # user_list = data[10:20]
    try:
        current_page = int(request.GET.get("page"))
    except Exception as e:
        current_page = 1

    per_page = 10

    # 数据总条数
    total_count = len(data)
    # 总页码
    total_page, more = divmod(total_count, per_page)
    if more:
        total_page += 1

    # 页面最多显示多少个页码
    max_show = 11
    half_show = int((max_show-1)/2)

    if current_page <= half_show:
        show_start = 1
        show_end = max_show
    else:
        if current_page + half_show >= total_page:
            show_start = total_page - max_show
            show_end = total_page
        else:
            show_start = current_page - half_show
            show_end = current_page + half_show

    # 数据库中获取数据
    data_start = (current_page - 1) * per_page
    data_end = current_page * per_page

    user_list = data[data_start:data_end]

    # 生成页面上显示的页码
    page_html_list = []
    # 加首页
    first_li = '<li><a href="/user_list/?page=1">首页</a></li>'
    page_html_list.append(first_li)
    # 加上一页
    if current_page == 1:
        prev_li = '<li><a href="#">上一页</a></li>'
    else:
        prev_li = '<li><a href="/user_list/?page={}">上一页</a></li>'.format(current_page - 1)
    page_html_list.append(prev_li)
    for i in range(show_start, show_end+1):
        if i == current_page:
            li_tag = '<li class="active"><a href="/user_list/?page={0}">{0}</a></li>'.format(i)
        else:
            li_tag = '<li><a href="/user_list/?page={0}">{0}</a></li>'.format(i)
        page_html_list.append(li_tag)

    # 加下一页
    if current_page == total_page:
        next_li = '<li><a href="#">下一页</a></li>'
    else:
        next_li = '<li><a href="/user_list/?page={}">下一页</a></li>'.format(current_page+1)
    page_html_list.append(next_li)

    # 加尾页
    page_end_li = '<li><a href="/user_list/?page={}">尾页</a></li>'.format(total_page)
    page_html_list.append(page_end_li)

    page_html = "".join(page_html_list)

    return render(request, "user_list.html", {"user_list": user_list, "page_html": page_html})

4858.com 31

4858.com 32

4858.com 33

class Pagination(object):
    def __init__(self, current_page, total_count, base_url, per_page=10, max_show=11):
        """
        :param current_page: 当前页
        :param total_count: 数据库中数据总数
        :param per_page: 每页显示多少条数据
        :param max_show: 最多显示多少页
        """
        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1

        self.current_page = current_page
        self.total_count = total_count
        self.base_url = base_url
        self.per_page = per_page
        self.max_show = max_show

        # 总页码
        total_page, more = divmod(total_count, per_page)
        if more:
            total_page += 1

        half_show = int((max_show - 1) / 2)
        self.half_show = half_show
        self.total_page = total_page

    @property
    def start(self):
        return (self.current_page - 1) * self.per_page

    @property
    def end(self):
        return self.current_page * self.per_page

    def page_html(self):

        if self.current_page <= self.half_show:
            show_start = 1
            show_end = self.max_show
        else:
            if self.current_page + self.half_show >= self.total_page:
                show_start = self.total_page - self.max_show
                show_end = self.total_page
            else:
                show_start = self.current_page - self.half_show
                show_end = self.current_page + self.half_show

                # 生成页面上显示的页码
        page_html_list = []
        # 加首页
        first_li = '<li><a href="{}?page=1">首页</a></li>'.format(self.base_url)
        page_html_list.append(first_li)
        # 加上一页
        if self.current_page == 1:
            prev_li = '<li><a href="#">上一页</a></li>'
        else:
            prev_li = '<li><a href="{0}?page={1}">上一页</a></li>'.format(self.base_url, self.current_page - 1)
        page_html_list.append(prev_li)
        for i in range(show_start, show_end + 1):
            if i == self.current_page:
                li_tag = '<li class="active"><a href="{0}?page={1}">{1}</a></li>'.format(self.base_url, i)
            else:
                li_tag = '<li><a href="{0}?page={1}">{1}</a></li>'.format(self.base_url, i)
            page_html_list.append(li_tag)

        # 加下一页
        if self.current_page == self.total_page:
            next_li = '<li><a href="#">下一页</a></li>'
        else:
            next_li = '<li><a href="{0}?page={1}">下一页</a></li>'.format(self.base_url, self.current_page + 1)
        page_html_list.append(next_li)

        # 加尾页
        page_end_li = '<li><a href="{0}?page={1}">尾页</a></li>'.format(self.base_url, self.total_page)
        page_html_list.append(page_end_li)

        return "".join(page_html_list)

4858.com 34

4858.com 35

4858.com 36

def user_list(request):
    pager = Pagination(request.GET.get("page"), len(data), request.path_info)
    user_list = data[pager.start:pager.end]
    page_html = pager.page_html()
    return render(request, "user_list.html", {"user_list": user_list, "page_html": page_html})

4858.com 37

扩展:

Django内置分页

4858.com 38

4858.com 39

from django.shortcuts import render
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

L = []
for i in range(999):
    L.append(i)

def index(request):
    current_page = request.GET.get('p')

    paginator = Paginator(L, 10)
    # per_page: 每页显示条目数量
    # count:    数据总个数
    # num_pages:总页数
    # page_range:总页数的索引范围,如: (1,10),(1,200)
    # page:     page对象
    try:
        posts = paginator.page(current_page)
        # has_next              是否有下一页
        # next_page_number      下一页页码
        # has_previous          是否有上一页
        # previous_page_number  上一页页码
        # object_list           分页之后的数据列表
        # number                当前页
        # paginator             paginator对象
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:
        posts = paginator.page(paginator.num_pages)
    return render(request, 'index.html', {'posts': posts})

4858.com 40

4858.com 41

4858.com 42

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<ul>
    {% for item in posts %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>

<div class="pagination">

        {% if posts.has_previous %}
            <a href="?p={{ posts.previous_page_number }}">Previous</a>
        {% endif %}

            Page {{ posts.number }} of {{ posts.paginator.num_pages }}.

          {% if posts.has_next %}
              <a href="?p={{ posts.next_page_number }}">Next</a>
          {% endif %}


</div>
</body>
</html>

4858.com 43

实惠时间内足以防登六(大家的一部分购物网址内部会有提醒新闻,几天以内是能够防登录,都以在cookie里面完毕的这么些意义)

Session流程解析

4858.com 44

铭记用户的少数浏览习于旧贯

Django中的Session配置

Django中暗许支持Session,其里面提供了八种档案的次序的Session供开辟者使用。settings.py文件中布局

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,默认修改之后才保存(默认)

大约的请求限制(举个例子在投票系统中,小编事先在博客园地点给中夏族民共和国有嘻哈的运动员投票的时候浏览器是会有限量的,无法极其次的在大势所趋时间内反复提交,系统提示一天只可以投三回票,那种状态正是cookie里面能够设置的操作)

CBV中加装饰器相关

CBV达成的登陆视图

class LoginView(View):

    def get(self, request):
        """
        处理GET请求
        """
        return render(request, 'login.html')

    def post(self, request):
        """
        处理POST请求 
        """
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        if user == 'alex' and pwd == "alex1234":
            next_url = request.GET.get("next")
            # 生成随机字符串
            # 写浏览器cookie -> session_id: 随机字符串
            # 写到服务端session:
            # {
            #     "随机字符串": {'user':'alex'}
            # }
            request.session['user'] = user
            if next_url:
                return redirect(next_url)
            else:
                return redirect('/index/')
        return render(request, 'login.html')

要在CBV视图中运用我们地方的check_login装饰器,有以下二种格局:

from django.utils.decorators import method_decorator

 

1. 加在CBV视图的get或post方法上

from django.utils.decorators import method_decorator


class HomeView(View):

    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    @method_decorator(check_login)
    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

我们的cookie里面保存的新闻在页面上是能够来得出来的,张开页面,按住键盘上行的f1二键,就能够展开network,里面能够见见请求头,在内部能够查阅到大家的cookie音信,那里就存在隐衷音讯外泄的高风险,大家一般都以会有加盐操作,就跟大家学md5的时候,那多少个加盐是千篇一律的概念,在大家的通晓新闻的底子上加一层密,同样,我们在后端加密之后必要解密,实现1来一遍的操作,cookie里面包车型地铁加盐也是salt

2. 加在dispatch方法上

from django.utils.decorators import method_decorator


class HomeView(View):

    @method_decorator(check_login)
    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

因为CBV中率先实践的正是dispatch方法,所以那样写一定于给get和post方法都助长了登入校验。

不加盐的cookie

三. 间接加在视图类上,但method_decorator必须传 name 关键字参数

如若get方法和post方法都亟待报到校验的话就写五个装饰器。

from django.utils.decorators import method_decorator

@method_decorator(check_login, name="get")
@method_decorator(check_login, name="post")
class HomeView(View):

    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

 

rep.set_cookie(“k1”, “v1”, max_4858.com,age=10)  # 那里是安装cookie

补充

CS奥迪Q5F
Token相关装饰器在CBV只能加到dispatch方法上,只怕加在视图类上然后name参数钦命为dispatch方法。

备注:

  • csrf_protect,为目前函数强制安装防跨站请求伪造功效,纵然settings中从未设置全局中间件。
  • csrf_exempt,撤销当前函数防跨站请求伪变成效,纵然settings中安装了全局中间件。

    from django.views.decorators.csrf import csrf_exempt, csrf_protect
    from django.utils.decorators import method_decorator

class HomeView(View):

    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

或者

from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator


@method_decorator(csrf_exempt, name='dispatch')
class HomeView(View):

    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

 

rep.cookie.get(‘k1’,None)  # 那里是得到cookie

Cookie和Session练习示例

说明:app01使用Cookie,app02使用Session

*  default:默认值

urls路由

4858.com 454858.com 46

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

from app01 import views as v1
from app02 import views as v2
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^app01/login/$', v1.login),
    url(r'^app01/home/$', v1.home),
    url(r'^app01/index/$', v1.index),
    url(r'^app01/logout/$', v1.logout),

    url(r'^app02/login/$', v2.login),
    url(r'^app02/home/$', v2.home),
    url(r'^app02/index/$', v2.index),
    url(r'^app02/logout/$', v2.logout),

    url(r'^app02/userinfo/$', v2.userInfo.as_view()),
]

urls.py

*  salt:加盐

templates

app01目录下:

4858.com 474858.com 48

# home.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>home</title>
</head>
<body>
<h1>这是home页面</h1>
<a href="app01/logout">注销</a>
</body>
</html>


# index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
<h1>这是Index页面</h1>
</body>
</html>


# login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
<h1>这是login页面</h1>
<form action="{{ request.get_full_path }}" method="post">
    {% csrf_token %}
    <p>
        用户名:
        <input type="text" name="user">
    </p>
    <p>
        密码:
        <input type="text" name="pwd">
    </p>
    <input type="submit" value="提交">
</form>
</body>
</html>

app0一目录下的html文件

app02目录下:

4858.com 494858.com 50

# home.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>home</title>
</head>
<body>
<h1>这是{{ user }}主页面</h1>
<a href="/app02/logout/">注销</a>
</body>
</html>


# index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
<h1>这是Index页面</h1>
</body>
</html>


# login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
<h1>这是login页面</h1>
<form action="{{ request.get_full_path }}" method="post">
    {% csrf_token %}
    <p>
        用户名:
        <input type="text" name="user">
    </p>
    <p>
        密码:
        <input type="text" name="pwd">
    </p>
    <input type="submit" value="提交">
</form>
</body>
</html>

app02目录下的html文件

*  max_age:后台调控过期时间

库克ie版登入验证

4858.com 514858.com 52

from django.shortcuts import render,redirect

# Create your views here.
from functools import wraps

def check_login(func):
    @wraps(func)    # 装饰器修复技术
    def inner(request, *args, **kwargs):
        # 已经登录过的 继续执行
        ret = request.get_signed_cookie("is_login", default="0", salt="jiayan")
        if ret == "1":
            return func(request, *args, **kwargs)
        # 没有登录过的 跳转到登录页面
        else:
            # 获取当前访问的URL
            next_url = request.path_info
            print(next_url)
            return redirect("/app01/login/?next={}".format(next_url))
    return inner

def login(request):
    print(request.get_full_path())  #获取当前请求的路径和参数
    print(request.path_info)    # 获取当前请求的路径
    if request.method == "POST":
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")
        # 从URL里面取到 next参数
        next_url = request.GET.get("next")
        if user == "root" and pwd == "root":
            # 登录成功
            # 告诉浏览器保存一个键值对

            if next_url:
                rep = redirect(next_url)  # 得到一个响应对象
            else:
                rep = redirect("/app01/home/")

            # 设置加盐的cookie
            rep.set_signed_cookie("is_login", "1", salt="jiayan", max_age=30)   # 设置超时时间 默认单位是秒
            return rep
    return render(request, "app01/login.html")

def home(request):
    # 从请求的cookie中查找有没有cookie
    # 取加盐过的cookie
    ret = request.get_signed_cookie("is_login", default="0", salt="jiayan")
    # ret = request.COOKIES.get("is_login", 0)
    if ret == "1":
        # 表示已经登录过
        return render(request, "app01/home.html")
    else:
        return redirect("/app01/login/")

@check_login
def index(request):
    return render(request, "app01/index.html")

# 注销函数
def logout(request):
    # 如何删除cookie
    rep = redirect("/app01/login/")
    rep.delete_cookie("is_login")
    return rep

Cookie版登入验证

  • expires=None, 超时时间(IE requires expires, so set it if hasn’t been
    already.)
  • path=’/’, Cookie生效的路子,/
    表示根路线,特殊的:根路线的cookie能够被此外url的页面访问
  • domain=None, Cookie生效的域名
  • secure=False, https传输
  • httponly=False
    只好http协议传输,不能被JavaScript获取(不是相对,底层抓包能够赢获得也足以被掩盖)

Session版登入验证

4858.com 534858.com 54

from django.shortcuts import render,redirect
from django.utils.decorators import method_decorator
from django import views
# Create your views here.
from functools import wraps

def check_login(func):
    @wraps(func)    # 装饰器修复技术
    def inner(request, *args, **kwargs):
        ret = request.session.get("is_login")
        # 1. 获取cookie中的随机字符串
        # 2. 更具随机字符串去数据库取 session_data ———> 解密 ———> 反序列化成字典
        # 3. 在字典里面 根据 is_login 取具体的数据
        if ret == "1":
            # 已经登录过的 继续执行
            return func(request, *args, **kwargs)
        # 没有登录过的 跳转到登录页面
        else:
            # 获取当前访问的URL
            next_url = request.path_info
            print(next_url)
            return redirect("/app02/login/?next={}".format(next_url))
    return inner

def login(request):
    if request.method == "POST":
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")
        # 从URL里面取到 next参数
        next_url = request.GET.get("next")
        if user == "root" and pwd == "root":
            # 登录成功
            # 告诉浏览器保存一个键值对

            if next_url:
                rep = redirect(next_url)  # 得到一个响应对象
            else:
                rep = redirect("/app02/home/")

            # 设置session
            request.session["is_login"] = "1"
            request.session["user"] = user
            request.session.set_expiry(7)
            return rep
    return render(request, "app02/login.html")

@check_login
def home(request):
    user = request.session.get("user")
    return render(request, "app02/home.html", {"user": user})

@check_login
def index(request):
    return render(request, "app02/index.html")

# 注销函数
def logout(request):
    # 只删除session数据
    request.session.delete()
    # 如何删除session数据和cookie
    request.session.flush()
    return redirect("/app02/login/")


# 给CBV视图加装饰器
class userInfo(views.View):
    @method_decorator(check_login)
    def get(self, request):
        return render(request, "app02/userinfo.html")

Session版本登陆验证

 

 

大家在views视图函数里面安装cookie,

设置在响应对象这里,我们的响应对象正是大家给浏览器提交2个呼吁,然后浏览器做出响应,这么些给大家回响应的函数正是大家的响应对象,说白了就是大家在url路由陈设内部的地址,提交它的时候给大家过来响应的视图函数,它正是响应对象

它里面加多cookie设置(加盐)

def login(request):
    if request.method == 'POST':
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        if user == 'alex' and pwd == 'who':
            rep = redirect('/index1/')  # 这里把回复的响应赋值给一个变量
#然后我们下面方便对它进行操作
# rep.set_cookie('user',user)
# import datetime
# now=datetime.timedelta(seconds=19)
# 这里下面就是我们的cookie设置,固定用法,关键字要写上,然后就是传参,参数也是有固定用法的,
# rep.set_signed_cookie('user3',user, salt='s3',expires=now+d)
            rep.set_signed_cookie('user3', user, salt='s3', max_age=100, path='/index1/')
            return rep
    return render(request, 'cookie/login.html')

 

一端设置了cookie,另一端要求去接受它

获取cookie:

def index1(request):
    user = request.get_signed_cookie('user3', None, salt='s3')
# 这里是获取参数,我们的参数需要跟上面对应上,
    if not user:
        return redirect('/login/')
    return render(request, 'cookie/index1.html', {"username": user})

 

删除cookie:

rep.delete_cookie(‘k’)

 

cookie版的报到校验:

4858.com 554858.com 56

def check_login(func):
    @wraps(func)
    def inner(request, *args,**kwargs):
        next_url=request.get_full_path()
        if request.get_signed_cookie('login',salt='sss',default=None)=='yes':
            # 已经登录的用户...
            return func(request,*args,**kwargs)
        else:
            # 没有登录的用户跳转到刚登陆的页面
            return redirect('/login/?next={}'.format(next_url))
    return inner


def login(request):
    if request.method=='POST':
    username=request.POST.get("username")
    passwd=request.POST.get("password")
    if username=="XXX" and passwd=='okok':
        next_url=request.GET.get('next')
        if next_url and next_url !='/logout/':
              response=redirect(next_url)
        else:
            response=redirect('/class_list/')
        response.set_signed_cookie('login','yes',salt='SSS')
        return response
    return render(request,'login.html')

View Code

 

 

 浏览器里面是有特意的安装选项,能够接纳不保留cookie,不过我们设置了不保留cookie之后,

登六一些页面包车型地铁时候就不只怕登陆成功,会有种类提醒cookie未有拉开,需求开启之后本事登陆上

大家的cookie本质是在url上面增添的键对值,它的主要用途正是做登陆军高校验用,

大家的市面上重要的登入校验有三种办法:

1.加盐的cookie

数量都是保存在客户的浏览器上,服务端是未曾怎么压力的,

2.session

 django中默许帮衬session,个中间提供了5种等级次序的session供开辟者使用:

数据库(默认)

缓存

文件

缓存+数据库

加密cookie

 数据库session

SESSION_ENGINE=’django.contrib.sessions.backends.db’ 
    # 引擎(默认)

缓存session

SESSION_ENGINE=’django.contrib.sessions.backends.cache’

SESSION_CACHE_ALLAS=’default’

# 使用的缓存外号(暗许内部存款和储蓄器缓存,也得以是memcache),此处别名依赖缓存的设置

文件Session

SESSION_ENGINE=’django.contrib.sessions.backends.file’

SESSION_FILE_PATH=None

#
缓存文件路线,假若为None,则动用tempfile模块获取了3个一时半刻地址tempfile.gettempdir()

缓存+数据库

SESSION_ENNGINE=’django.contrib.sessions.backends.cached-db’

加密cookie Session

SESSION_ENGINE=’django.contrib.sessions.backends.signed_cookies’

其它的效应设置项:

4858.com 574858.com 58

SESSION_COOKIE_NAME='sessionid'
# session的cookie保存在浏览器上是的key,即sessionid=随机字符串(默认)
SESSION_COOKIE_PATH='/'
# session的bookie保存路径(默认)
SESSION_COOKIE_DAMAIN=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,默认修改之后才保存(默认)

View Code

 

不论你怎么设置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']

# 所有键,值,键值对
    request.sessin.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')
    # 删除当前用户的所有sessison数据
    request.session.delete()

    request.session.set_expiry(value)
* 如果value是个整数,session会在些秒数后失效
*如果value是个datatime或timedelta.session就会在这个时间之后失效
*如果value是0用户关闭浏览器session就会失效
*如果value是None,session会依赖全局session失效策略

django 操作session的时候,都是request.xxx

session

是保留在服务端的’键对值’数据

session必供给依据于cookie

咱俩的session里面包车型地铁键对值多少是在大家成立django项目的时候,自动生成的django_session的数据库表格里面,它会系统自动保存进去,

报表里面包车型大巴字段有session_key(键)

session_data(值)

expire_date(失效时间)那里一般是暗许值1四天过后就会自行清空,为了消除数据库的压力,那几个数量不会永世保存下去的,

笔者们应用session的时候,它里面须求做的几件事,:

一生成自由字符串

1遍给浏览器,让它写到cookie

三融洽保留一份,作为三个key,存到三个地方,key后边对应几个封存用户相关音信的键值对

 

咱俩那边补充有个别session的知识点

大家要验证大家的浏览器是还是不是带有cookie或session,假诺有name就在我们的auth_session表格里面填入一条数据,借使未有那么就新添一条数据,那是浏览器等第的,

大家的一个浏览器里面就保留1组键值对,key是浏览器等第的cookie和session,那么value正是咱们的用户信息,我们登陆之后我们的用户品级的cookie和session就会以data的字典格局保存在auth_user里面,若是在同三个浏览器里面有七个用户登入了,那么,大家后登录的用户新闻就会覆盖后面包车型大巴用户消息,然后替换掉后边的数码存入大家的键值对其中的值里面.

 

 Session版登入验证

 

from functools import wraps  # 这里是引入一个修复装饰器的模块或者是内置方法

def check_login(func):
    @wraps(func)
    def inner(request,*args,**kwargs):
        next_url=request.get_full_path()
        if request.sessionget('user'):
            return func(request,*args,**kwargs)
        else:
            return redirect('/login/?next={}'.format(next_url))
    return inner


def login(request):
    if request.method=='POST':
        user=request.POST.get('user')
        pwd=request.POST.get('pwd')

        if user=='alex' and pwd='123':
# 设置session
            request.session['uesr']=user
# 获取调到登录页面之前的url (我们在浏览一个网页的时候有的内容是需要登录之后才可以查看的,那个时候我们可能正停留在F页面,然后我们登录完之后,需要系统自动捕获到我们当时停留的页面,然后我们遇到需要登录提示之后我们去进行登录,登录完之后系统要把捕获到的我们当时在登录之前停留的
页面提交给我们,然后我们就可以继续做我们的事.如果没有这个捕获当前停留页面的功能的话,我们登录完成之后就给我们返回到了A页,然后我们要继续作业的话就要从A页一直一直刷到F页才能继续我们接下来的作业,那样的效率就太低下了,所以这个功能是很必要的)

            next_url=request.GET.get('next')
            if next_rul:
                return redirect(next_url)
            else:
                return redirect('/index/')
    return render(request.'login.html')

@check_login
def logout(request):
#删除所有当前请求相关的session
    request.session.delete()
    return redirect('/login/')

@ched_login
def index(request):
      current_user=request.session.get('user',None)
      return render(request,'index.html',{'user':current_user})  

 

 CBV落成的报到视图

class LoginView(View):
    def get(self,request):
"""处理get请求"""
        return render(request,'login.html')

def post(self,request):
    """处理post请求"""
    user=request.POST.get('user')
    pwd=request.POST.get('pwd')
    if uesr=='alex' and pwd=='123':
        next_url=request.GET.get('next')
# 生成随机字符串
#写浏览器cookie>session_id:随机字符串
#写到服务端session:
#{
#'随机字符串':{'user':'alex'}
#}
        request.session['user']=user
        if next_url:
            return redirect(next_url)
        else:
            return redirect('/index/')
    return render(request,'login.html')

 

在CBV视图中采取大家的方面包车型客车check_login装饰器,有以下两种艺术:

from django.utils.decorators import method_decorator

1加在CBV视图的get或post方法上

 

from django.utils.decorators import method_decorator

class HomeView(View):
    def dispatch(self,request,*args,**kwargs):
        return super(HoneVies,self).dispatch(request,*args,**kwargs)

    def get(self,request):
        return render(request,'home.html')

    @method_decorator(check_login)
    def post(self,request):
        print('home view post method...')
        return redirect('/index/')

 

加在dispatch方法上

from django.utils.decorators import method_decorator

class HomeView(View):
    @method_decorator(check_login)
    def dispatch(self,request,*args,**kwargs):
        return super(HomeView,self).dispatch(request,*args,**kwargs)

    def get(self,request):
        return render(request,'home.html')

    def post(self,request):
        print('home  view post method...')
        return redirect('/index/')

 

比如get方法和post方法都须求报到校验就写五个装饰器

from django.utils.decorators import method_decorator

@method_decorator(check_login,name='get')
@method_decorator(check_login,name='post')
class HomeView(View):

    def dispatch(self,request,*args,**kwargs):
        return super(HomeView,self).dispatch(request,*args,**kwargs)

    def get(self,request):
        return render(request,'home.html')

    def post(self,request):
        print('home view post method...')
        return redirect('/index/')

 

补充:

CS本田UR-VF Token 相关装饰器在CBV只好加到dispatch方法上

备注:csrf_tprotect,为当前函数强制安装防跨站请求伪造作用,尽管setting中从不设置全局中间件

csrf_exempt,撤除当前函数防跨站请求伪造功效,尽管setting中装置了大局中间件

from django,views.decorators.csrf import csrf_exempt, csrf_protect

class HomeView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self,request,*args,**kwargs):
        return super(HomeView,self).dispatch(request,*args,**kwargs)

    def get(self,request):
        return render(request,'home.html')

    def post(self,request):
        print('home view post method...')
        return redirect('/index/')

 

 

 

咱们的分页展现效果:

规行矩步大家的django框架的步骤,先从我们的url配置内部开头,

url配置:

url(r'^list/$',views.user_list,),

 

下一场跳转到views里面包车型地铁视图函数:

# 这里我们是伪造的一个数据组,模拟数据库里面的数据取值,
data=[]
for i in range(i,303):
  tmp={'id':i,'name':'alex-{}'.format(i)}
  data.append(tmp)


def user_list(request):
    page_num=request.GET.get('page')
    path=request.path_info
    from .tool import MyPage
    page_html=page.page_html()
    return render(request,'user_list.html',{'user_list':data[page.start:page.end],'page_html':page_html})

引进的类的文本:

4858.com 594858.com 60

# 分页封装方法
class MyPage(object):

    def __init__(self, page_num, total_count, base_url, per_page_num=10, max_show=11):
        """

        :param page_num: 当前页面
        :param total_count: 数据总个数
        :param base_url: 分页页码跳转的url
        :param per_page_num: 每一页显示多少条数据
        :param max_show: 页面上最多显示多少页码
        """
        # 实例化时传进来的参数
        try:
            self.page_num = int(page_num)

        except Exception as e:
            self.page_num = 1
        self.total_count = total_count
        self.base_url = base_url
        self.per_page_num = per_page_num
        self.max_show = max_show
        self.half_show = int((self.max_show-1)/2)
        self.total_page_num, more = divmod(self.total_count, self.per_page_num)
        if more:
            self.total_page_num += 1

    @property
    def start(self):
        return (self.page_num-1)*self.per_page_num

    @property
    def end(self):
        return self.page_num*self.per_page_num

    def page_html(self):
        """
        返回页面上可以用的一段HTML
        一段可用的分页页码的HTML
        :return:
        """
        # 页面上页码从哪儿开始
        page_start = self.page_num-self.half_show
        page_end = self.page_num+self.half_show
        if self.page_num <= self.half_show:
            page_start = 1
            page_end = self.max_show
        if self.page_num >= self.total_page_num-self.half_show:
            page_end = self.total_page_num
            page_start = self.total_page_num-self.max_show

        # 生成前页码的HTML
        page_html_list = []

        # 生成第一页
        page_first_tmp = '<li><a href="{}?page=1">首页</a><li>'.format(self.base_url)
        page_html_list.append(page_first_tmp)

        # 生成上一页
        if self.page_num-1 <= 0:
            page_prev_tmp = '<li><a href="#">上一页</a></li>'
        else:
            page_prev_tmp = '<li><a href="{0}?page={1}">上一页</a></li>'.format(self.base_url, self.page_num-1)

        page_html_list.append(page_prev_tmp)

        # 生成页码中间页数前半截
        for i in range(page_start, page_end+1):
            if i == self.page_num:
                tmp = '<li class="active"><a href="{0}?page={1}">{1}</a></li>'.format(self.base_url, i)
            else:
                tmp = '<li><a href="{0}?page={1}">{1}</a></li>'.format(self.base_url, i)

            page_html_list.append(tmp)

        # 生成页码中间页数后半截
        if self.page_num+1 > self.total_page_num:
            page_next_tmp = '<li class="disabled"><a href="#">下一页</a></li>'
        else:
            page_next_tmp = '<li><a href="{0}?page={1}">下一页</a></li>'.format(self.base_url, self.page_num+1)

        page_html_list.append(page_next_tmp)

        # 生成最后一页
        page_last_tmp = '<li><a href="{0}?page={1}">尾页</a></li>'.format(self.base_url, self.total_page_num)
        page_html_list.append(page_last_tmp)

        return "".join(page_html_list)

View Code

html页面:

4858.com 614858.com 62

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>用户列表</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7/css/bootstrap.min.css">

</head>
<body>
{#我们使用bootstrap的时候需要用div标签class里面设置一个container属性去进行装饰它#}

<div class="container">
    <table class="table table-bordered">
        <thead>
        <tr>
            <th>ID</th>
            <th>姓名</th>
        </tr>
        </thead>

        <tbody>
        {% for user in user_list %}
{#            为什么我们这里取不到值呢#}
            <tr>
                <td>{{ user.id }}</td>
                <td>{{ user.name }}</td>
            </tr>
        {% endfor %}
        </tbody>
    </table>
    <div class="pull-right">
        <!--分页开始-->
        <nav aria-label="Page navigation">
            <ul class="pagination">
                {#            {% for i in total_page_num %}#}
                <li><a href="{{ base_url }}?page={{ i }}"></a></li>
                {#            {% endfor %}#}
                {{ page_html|safe }}
                {# 这里我们使用了|safe参数,是把这里作为一个字符串跟我们的后端逻辑代码去关联,然后我们把后端的代码转成字符串传过来我们的前端就可以显示出来了#}
            </ul>
        </nav>
        <!--分页结束-->
    </div>

</div>
</body>
</html>

View Code

 

 

在django的布置文件setting中,有四个布局参数是时刻与时区有关的,分别是TIME_ZONE和USE_TZ

如果是USE_TZ设置为True时,django会使用系统暗中认可设置的时区,即America/Chicago,此时的TIME_ZONE不管有未有设置都不起成效.

 

如果USE_TZ设置为False,而TIME_ZONE设置为None,则django照旧会动用暗许的America/Chicago时间,

 

若TIME_ZONE设置为此外时区的话,则还要分情形,借使是windows系统,则TIME_ZONE设置是不曾用的,django会使用本机的年月,倘若为任何系统,则选择该时区的岁月,如设置USE_TZ=False,TIME_ZONE=’Asia/Shanghai”,则选用香港的UTC时间

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有