python 学习笔记十九 django深入学习四 cookie,session
缓存
一个动态网站的基本权衡点就是,它是动态的。 每次用户请求一个页面,Web服务器将进行所有涵盖数据库查询到模版渲染到业务逻辑的请求,用来创建浏览者需要的页面。当程序访问量大时,耗时必然会更加明显,这就是需要缓存的地方,缓存一些东西是为了保存那些需要很多计算资源的结果,这样的话就不必在下次重复消耗计算资源。
Django自带了一个健壮的缓存系统来让你保存动态页面这样避免对于每次请求都重新计算。方便起见,Django提供了不同级别的缓存粒度:你可以缓存特定视图的输出、你可以仅仅缓存那些很难生产出来的部分、或者你可以缓存你的整个网站。
Django支持 开发调试,内存,mysql,Redis、Memecache、文件的方式做缓存,并且可以设置超时时间。
设置缓存(基于文件)
settings
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', # 引擎 'LOCATION': os.path.join(BASE_DIR, 'cache'), # cache文件的存放路径 'TIMEOUT': 600, # 缓存超时时间(默认300,None表示永不过期,0表示立即过期) 'OPTIONS': { 'MAX_ENTRIES': 1000 # 最大缓存个数(默认300) } } }
urls
配置如下: from django.conf.urls import url from django.contrib import admin from app01 import views #导入app的views函数 urlpatterns = [ url(r'^admin/', admin.site.urls), #设置当用户访问ip:端口/time时候使用这个函数 url(r'cache/',views.cache_page), ]
views
from django.views.decorators.cache import cache_page from django.shortcuts import render,HttpResponse #这里设置的是 60秒 * 15 ,15分钟之后 @cache_page(60 * 15) def cache_page(request): current = str(time.time()) return HttpResponse(current)
cookie 和 session
Cookie 保存于本地 ,session 保存于服务器;同时我们也看到,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,
所以session机制可能需要借助于cookie机制来达到保存标识的目的,但实际上它还有其他选择。
区别:
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
工作流程:
当你浏览京东或者天猫的时候,登录成功以后(一次请求),想查看我的订单(另一次请求),但是http是短连接(连接一次就断开),服务器该如何判断你是否登录呢?所以在服务器端需要有一个保存用户状态地方(session),客户端登录成功后,服务端向客户端浏览器写入一段字符串(标识),客户端每次访问的时候需要带上这个标识,服务端根据这个标识就能获取客户端信息了。客户端保存这个标识就叫做cookie。
构成:
1、自动生成一段字符串
2、将字符串发送到客户端的浏览器(cookie),同时把这段字符串当做key放在session里。(可以理解为session就是一个字典)
3、在用户的session对应的value里设置任意值(字典里面可以继续套字典)
session基本操作
- 获取session:request.session[key]
- 设置session:reqeust.session[key] = value
- 删除session:del request.session[key]
request.session.set_expiry(value)
* 如果value是个整数,session会在些秒数后失效。
* 如果value是个datatime或timedelta,session就会在这个时间后失效。
* 如果value是0,用户关闭浏览器session就会失效。
* 如果value是None,session会依赖全局session失效策略。
实例:
# views
from django.shortcuts import render,HttpResponseRedirect # Create your views here. def index(request): #从请求里获取username session #首先判断存不存在session,如果不存在跳转到login页面 is_login = request.session.get("is_login", False)
if is_login:
# 这里可以根据登录的用户显示不同的数据
# username = request.session.get("username")
# retrun render(request,"xxx.html")
return httpResponse("index")
else:
return redirect("/login/")
def login(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') if username == "koka" and password=="123456":
# 设置session request.session['is_login'] = True
# 可以设置多个值
request.session["username"] = username
return redirect('/index/')
return render(request, "login.html") def logout(request):
#删除session del request.session["session_name"]
return redirect('/login/')
注:session默认用的是数据库,所以需要初始化数据库。
1.python manage.py makemigrations 2.python manage.py mirate
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/login/" method="post">{% csrf_token %} 用户名:<input type="text" name="username"/> 密码:<input type="password" name="password"/> <input type="submit" value="登录"/> </form> </body> </html>
扩展:Session用户验证
def login(func): def wrap(request, *args, **kwargs): # 如果未登陆,跳转到指定页面 if request.path == '/test/': return redirect('http://www.baidu.com') return func(request, *args, **kwargs) return wrap
cookie操作:
1.设置cookie
1 request.COOKIES['key'] 2 request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None) 3 参数: 4 default: 默认值 5 salt: 加密盐 6 max_age: 后台控制过期时间
2.获取cookie
1 rep = HttpResponse(...) 或 rep = render(request, ...) 2 3 rep.set_cookie(key,value,...) 4 rep.set_signed_cookie(key,value,salt='加密盐',...) 5 参数: 6 key, 键 7 value='', 值 8 max_age=None, 超时时间 9 expires=None, 超时时间(IE requires expires, so set it if hasn't been already.) 10 path='/', Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问 11 domain=None, Cookie生效的域名 12 secure=False, https传输 13 httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie。
1 <script src='/static/js/jquery.cookie.js'></script> 2 $.cookie("list_pager_num", 30,{ path: '/' });
django 用户认证
使用session或者cookie验证,需要在每一个views都需要修改源代码添加验证机制,我们可以用到装饰器。django提供了用户验证的方法和验证用户登录的装饰器。
django提供了authentication,log,logout,login_required的方法:
Authenticating users
from django.contrib.auth import authenticate user = authenticate(username='john', password='secret') if user is not None: # the password verified for the user if user.is_active: print("User is valid, active and authenticated") else: print("The password is valid, but the account has been disabled!") else: # the authentication system was unable to verify the username and password print("The username and password were incorrect.")
login
from django.contrib.auth import authenticate, login def my_view(request): username = request.POST['username'] password = request.POST['password'] user = authenticate(username=username, password=password) if user is not None: if user.is_active: login(request, user) # Redirect to a success page. else: # Return a 'disabled account' error message ... else: # Return an 'invalid login' error message. ...
logout
from django.contrib.auth import logout def logout_view(request): logout(request) # Redirect to a success page.
login_required
在需要验证登录的views函数上添加login_required
from django.contrib.auth.decorators import login_required @login_required def my_view(request): ...
实例:
views
from django.shortcuts import render,HttpResponseRedirect from django.contrib.auth.decorators import login_required from django.contrib.auth import authenticate, login, logout # Create your views here. @login_required def index(request): return render(request, 'index.html') def acc_login(request): if request.method == 'POST': print(request.POST) user = authenticate(username=request.POST.get('username'), password=request.POST.get('password')) if user is not None: # pass authentication login(request, user) return HttpResponseRedirect('/') else: login_err = "Wrong username or password!" return render(request, 'login.html', {'login_err': login_err}) return render(request, 'login.html') def acc_logout(request): logout(request) return HttpResponseRedirect('/')
urls
from django.conf.urls import include, url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^$', views.index), url(r'^accounts/login/$', views.acc_login), url(r'^accounts/logout/$', views.acc_logout), ]
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1> Oldboy CRM</h1> {% block page-container%} Welcome To Oldoby CRM <div> {% if request.user.is_authenticated %} <span>{{ request.user.userprofile.name }}</span> {% else %} <span>登陆/注册</span> {% endif %} </div> <a href="/accounts/logout/">退出系统</a> {% endblock %} </body> </html>
{% extends 'index.html' %} {% block page-container %} <form action="" method="post">{% csrf_token %} Username:<input type="text" name="username"> Password:<input type="password" name="password"> <input type="submit" value="Log me in"> <div> {% if login_err %} <p style="color: red">{{ login_err }}</p> {% endif %} </div> </form> {% endblock %}
参考链接:https://docs.djangoproject.com/en/1.9/topics/auth/default/#how-to-log-a-user-out
Ajax
1、单条数据提交
html
<form action="/user_list/" method="post"> <input type="button" onclick="Ajaxsubmit();" value="提交"/> <table> <thead> <tr> <th>主机名</th> <th>端口</th> </tr> </thead> <tbody> <tr> <td>1.1.1.1</td> <td>80000</td> </tr> <tr> <td>1.1.1.1</td> <td>80000</td> </tr> </tbody> </table> </form> <script type="text/javascript" src="/static/jquery-2.2.1.min.js"></script> <script> function Ajaxsubmit(){ var host = '1.1.1.1'; var port = '8000'; $.ajax({ url:"/ajax_data/", type:'POST', data:{h:host,p:port}, success:function(arg){ } }) } </script>
jquery代码:
function Ajaxsubmit(){ var host = '192.168.1.100'; var port = '8000';
$.ajax({ url:"/ajax_data/", #目标URL type:'POST', #请求方式 data:{h:host,p:port}, success:function(arg){ console.log(arg) }
})
}
urls
url(r'^ajax_data/', views.ajax_data),
views
def ajax_data(request):
print request.POST
return HttpResponse('OK')
2、ajax多条数据提交
在原来的基础上修改Jquery,jquery代码:
<script> function Ajaxsubmit(){ var array_users = [ {'username':'koka','arg':18}, {'username':'akok','arg':18}, {'username':'kako','arg':18}, ]; $.ajax({ url:"/ajax_mdata/", type:'POST',
# 以原生的模式传过去 tradition: true,
#把数组json序列化转成字符串
data:{data:JSON.stringify(array_users)}, success:function(arg){ var callback_dict = $.parseJSON(arg);//json反序列化把字符串转换为对象
if(callback_dict){
alert('提交成功') }
else{
alert(callback_dict.error)
} } }) } </script>
urls
url(r'^ajax_mdata/$', views.ajax_mdata),
views
import json
def ajax_data(request):
ret = {'status':True,'error':''}
try:
print request.POST
except Exception,e:
ret['status'] = False
ret['error'] = str(e)
#在上面如果他出错我就把他ret[status] = False
return HttpResponse(json.dumps(ret))
更多内容见:
http://www.cnblogs.com/wupeiqi/articles/5246483.html
http://www.cnblogs.com/luotianshuai/p/5278175.html