Session与Ajax
来源:互联网 发布:打蛋器价格淘宝 编辑:程序博客网 时间:2024/05/23 02:07
Django完全支持也匿名会话,简单说就是使用跨网页之间可以进行通讯,比如显示用户名,用户是否已经发表评论。session框架让你存储和获取访问者的数据信息,这些信息保存在服务器上(默认是数据库中),以 cookies 的方式发送和获取一个包含 session ID的值,并不是用cookies传递数据本身。
启用session
编辑settings.py中的一些配置
MIDDLEWARE_CLASSES 确保其中包含以下内容
'django.contrib.sessions.middleware.SessionMiddleware'
,
INSTALLED_APPS 是包含
'django.contrib.sessions'
,
这些是默认启用的。如果你不用的话,也可以关掉这个以节省一点服务器的开销。
提示:您也可以配置使用比如 cache 来存储 session
在视图中使用 session
request.session 可以在视图中任何地方使用,它类似于python中的字典
session 默认有效时间为两周,可以在 settings.py 中修改默认值:参见这里
# 创建或修改 session:
request.session[key]
=
value
# 获取 session:
request.session.get(key,default
=
None
)
# 删除 session
del
request.session[key]
# 不存在时报错
session 例子
比如写一个不让用户评论两次的应用:
from
django.http
import
HttpResponse
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."
)
当登陆时验证用户名和密码,并保存用户id在 session 中,这样就可以在视图中用 request.session['member_id']来检查用户是否登陆,当退出的时候,删除掉它。
有时候我们想把一个 list 或 dict等 JSON对象 传到网页的 javascript,用 JS 进行处理,比如用 js 将数据可视化显示到网页上。
请注意:如果不需要处理,直接显示到网页上,用Django模板就可以了,请看前面的教程。
这里讲述两种方法:
一,页面加载完成后,在页面上操作,在页面上通过 ajax 方法得到新的数据(再向服务器发送一次请求)并显示在网页上,这种情况适用于页面不刷新的情况下,动态加载一些内容。比如用户输入一个值或者点击某个地方,动态地把相应内容显示在网页上。
这种请问详见 Django Ajax 一节的内容。
二,直接在视图函数(views.py中的函数)中将 JSON对象 和网页其它内容一起传递到Django模板(一次性地渲染,还是同一次请求)。
请看下面的示例:
views.py
from
__future__
import
unicode_literals
from
django.shortcuts
import
render
def
home(request):
List
=
[
'自强学堂'
,
'渲染Json到模板'
]
return
render(request,
'home.html'
, {
'List'
:
List
})
home.html 中的一部分
<
script
type
=
"text/javascript"
>
var List = {{ List }};
alert(List);
</
script
>
需要注意的是,我们如果直接这么做,传递到 js 的时候,网页的内容会被转义,得到的格式会报错。
访问时会得到 Uncaught SyntaxError: Unexpected token ILLEGAL
需要注意两点:
1. 视图函数中的字典或列表要用 json.dumps()处理。
2. 在模板上要加 safe 过滤器。
views.py
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
import
json
from
django.shortcuts
import
render
def
home(request):
List
=
[
'自强学堂'
,
'渲染Json到模板'
]
Dict
=
{
'site'
:
'自强学堂'
,
'author'
:
'涂伟忠'
}
return
render(request,
'home.html'
, {
'List'
: json.dumps(
List
),
'Dict'
: json.dumps(
Dict
)
})
home.html 只给出了 js 核心部分:
//列表
var List = {{ List|safe }};
//字典
var Dict = {{ Dict|safe }};
如果你对 js 比较熟悉,到此为止,后面的不用看了。
如果不太熟悉,可以参考下面的更详细的代码。
html 完全代码及完整代码下载(最后面):
<!DOCTYPE html>
<
html
>
<
head
>
<
title
>欢迎光临 自强学堂!</
title
>
<
script
src
=
"http://apps.bdimg.com/libs/jquery/1.10.2/jquery.min.js"
></
script
>
</
head
>
<
body
>
<
div
id
=
"list"
> 学习 </
div
>
<
div
id
=
'dict'
></
div
>
<
script
type
=
"text/javascript"
>
//列表
var List = {{ List|safe }};
//下面的代码把List的每一部分放到头部和尾部
$('#list').prepend(List[0]);
$('#list').append(List[1]);
console.log('--- 遍历 List 方法 1 ---')
for(i in List){
console.log(i);// i为索引
}
console.log('--- 遍历 List 方法 2 ---')
for (var i = List.length - 1; i >= 0; i--) {
// 鼠标右键,审核元素,选择 console 可以看到输入的值。
console.log(List[i]);
};
console.log('--- 同时遍历索引和内容,使用 jQuery.each() 方法 ---')
$.each(List, function(index, item){
console.log(index);
console.log(item);
});
// 字典
var Dict = {{ Dict|safe }};
console.log("--- 两种字典的取值方式 ---")
console.log(Dict['site']);
console.log(Dict.author);
console.log("--- 遍历字典 ---");
for(i in Dict) {
console.log(i + Dict[i]);//注意,此处 i 为键值
}
</
script
>
</
body
>
</
html
>
完整代码下载:zqxt_json.zip (基于Django 1.8,注意settings.py文件和低版本可能不兼容,其它部分相同)
有时候我们需要在不刷新的情况下载入一些内容,在网页的基本知识中我们介绍了 ajax 技术。
在本文中讲解如何用 Django 来实现 不刷新网页的情况下加载一些内容。
由于用 jQuery 实现 ajax 比较简单,所以我们用 jQuery库来实现,想用原生的 javascript 的同学可以参考:ajax 教程,下面也有例子提供下载。
本节有多个实例提供下载,通过看代码可以更快的学习。
第一节,源代码下载:zqxt_ajax_1.zip
这里用 Django 表单 第一节 中的一个例子,我们要实现的是在不刷新的情况下显示计算结果到页面上。
修改 index.html 文件
<!DOCTYPE html>
<
html
>
<
body
>
<
p
>请输入两个数字</
p
>
<
form
action
=
"/add/"
method
=
"get"
>
a: <
input
type
=
"text"
id
=
"a"
name
=
"a"
> <
br
>
b: <
input
type
=
"text"
id
=
"b"
name
=
"b"
> <
br
>
<
p
>result: <
span
id
=
'result'
></
span
></
p
>
<
button
type
=
"button"
id
=
'sum'
>提交</
button
>
</
form
>
<
script
src
=
"http://apps.bdimg.com/libs/jquery/1.11.1/jquery.min.js"
></
script
>
<
script
>
$(document).ready(function(){
$("#sum").click(function(){
var a = $("#a").val();
var b = $("#b").val();
$.get("/add/",{'a':a,'b':b}, function(ret){
$('#result').html(ret)
})
});
});
</
script
>
</
body
>
</
html
>
在原来的基础上,在一些元素上加了 id, 以便于获取值和绑定数据,然后我们用了jQuery.get() 方法,并用 $(selector).html() 方法将结果显示在页面上,如下图:
备注:关于请求头和 request.is_ajax() 方法使用
views.py 中可以用 request.is_ajax() 方法判断是否是 ajax 请求,需要添加一个 HTTP 请求头:
原生javascript:
xmlhttp.setRequestHeader(
"X-Requested-With"
,
"XMLHttpRequest"
);
用 jQuery:
用 $.ajax 方法代替 $.get,因为 $.get 在 IE 中不会发送 ajax header
服务器端会将请求头的值全部大写,中划线改成下划线,并在非标准的头前面加上 HTTP_,这个过程可以认为相当于以下Python代码:
STANDARD_HEADERS
=
[
'REFER'
,
'HOST'
, ...]
# just for example
def
handle_header(value):
value
=
value.replace(
'-'
,
'_'
).upper()
if
value
in
STANDARD_HEADERS:
return
value
return
'HTTP_'
+
value
判断ajax方法,以及原生的 javascript实现ajax的示例下载:zqxt_views_ajax.zip
第二节,源代码下载:zqxt_ajax_list_dict.zip
更复杂的例子,传递一个数组或字典到网页,由JS处理,再显示出来。
views.py
from
django.http
import
HttpResponse
import
json
def
ajax_list(request):
a
=
range
(
100
)
return
HttpResponse(json.dumps(a), content_type
=
'application/json'
)
def
ajax_dict(request):
name_dict
=
{
'twz'
:
'Love python and Django'
,
'zqxt'
:
'I am teaching Django'
}
return
HttpResponse(json.dumps(name_dict), content_type
=
'application/json'
)
Django 1.7 及以后的版本有更简单的方法(使用 JsonResponse(官方文档)):
from
django.http
import
JsonResponse
def
ajax_list(request):
a
=
range
(
100
)
return
JsonResponse(a, safe
=
False
)
def
ajax_dict(request):
name_dict
=
{
'twz'
:
'Love python and Django'
,
'zqxt'
:
'I am teaching Django'
}
return
JsonResponse(name_dict)
在 django 1.6 及以前的旧版本中可以自己写一个 JsonResponse 方法,如下:
from
django.http
import
HttpResponse
import
json
class
JsonResponse(HttpResponse):
def
__init__(
self
,
content
=
{},
mimetype
=
None
,
status
=
None
,
content_type
=
'application/json'
):
super
(JsonResponse,
self
).__init__(
json.dumps(content),
mimetype
=
mimetype,
status
=
status,
content_type
=
content_type)
写好后,我们在 urls.py 中添加以下两行:
url(r
'^ajax_list/$'
,
'tools.views.ajax_list'
, name
=
'ajax-list'
),
url(r
'^ajax_dict/$'
,
'tools.views.ajax_dict'
, name
=
'ajax-dict'
),
打开开发服务器 python manage.py runserver
我们访问对应的网址会看到输出值:
下一步就是在无刷新的情况下把内容加载到网页了,我们修改一下首页的模板 index.html
<!DOCTYPE html>
<
html
>
<
body
>
<
p
>请输入两个数字</
p
>
<
form
action
=
"/add/"
method
=
"get"
>
a: <
input
type
=
"text"
id
=
"a"
name
=
"a"
> <
br
>
b: <
input
type
=
"text"
id
=
"b"
name
=
"b"
> <
br
>
<
p
>result: <
span
id
=
'result'
></
span
></
p
>
<
button
type
=
"button"
id
=
'sum'
>提交</
button
>
</
form
>
<
div
id
=
"dict"
>Ajax 加载字典</
div
>
<
p
id
=
"dict_result"
></
p
>
<
div
id
=
"list"
>Ajax 加载列表</
div
>
<
p
id
=
"list_result"
></
p
>
<
script
src
=
"http://apps.bdimg.com/libs/jquery/1.11.1/jquery.min.js"
></
script
>
<
script
>
$(document).ready(function(){
// 求和 a + b
$("#sum").click(function(){
var a = $("#a").val();
var b = $("#b").val();
$.get("/add/",{'a':a,'b':b}, function(ret){
$('#result').html(ret);
})
});
// 列表 list
$('#list').click(function(){
$.getJSON('/ajax_list/',function(ret){
//返回值 ret 在这里是一个列表
for (var i = ret.length - 1; i >= 0; i--) {
// 把 ret 的每一项显示在网页上
$('#list_result').append(' ' + ret[i])
};
})
})
// 字典 dict
$('#dict').click(function(){
$.getJSON('/ajax_dict/',function(ret){
//返回值 ret 在这里是一个字典
$('#dict_result').append(ret.twz + '<
br
>');
// 也可以用 ret['twz']
})
})
});
</
script
>
</
body
>
</
html
>
技能提升:getJSON中的写的对应网址,用 urls.py 中的 name 来获取是一个更好的方法!
标签:{% url 'name' %}
<script>
$(document).ready(
function
(){
// 求和 a + b
$(
"#sum"
).click(
function
(){
var
a = $(
"#a"
).val();
var
b = $(
"#b"
).val();
$.get(
"{% url 'add' %}"
,{
'a'
:a,
'b'
:b},
function
(ret){
$(
'#result'
).html(ret);
})
});
// 列表 list
$(
'#list'
).click(
function
(){
$.getJSON(
"{% url 'ajax-list' %}"
,
function
(ret){
//返回值 ret 在这里是一个列表
for
(
var
i = ret.length - 1; i >= 0; i--) {
// 把 ret 的每一项显示在网页上
$(
'#list_result'
).append(
' '
+ ret[i])
};
})
})
// 字典 dict
$(
'#dict'
).click(
function
(){
$.getJSON(
"{% url 'ajax-dict' %}"
,
function
(ret){
//返回值 ret 在这里是一个字典
$(
'#dict_result'
).append(ret.twz +
'<br>'
);
// 也可以用 ret['twz']
})
})
});
</script>
这样做最大的好处就是在修改 urls.py 中的网址后,不用改模板中对应的网址。
补充:如果是一个复杂的 列表 或 字典,因为比如如下信息:
person_info_dict
=
[
{
"name"
:
"xiaoming"
,
"age"
:
20
},
{
"name"
:
"tuweizhong"
,
"age"
:
24
},
{
"name"
:
"xiaoli"
,
"age"
:
33
},
]
这样我们遍历列表的时候,每次遍历得到一个字典,再用字典的方法去处理,当然有更简单的遍历方法:
用 $.each() 方法代替 for 循环,html 代码(jQuery)
$.getJSON(
'ajax-url-to-json'
,
function
(ret) {
$.each(ret,
function
(i,item){
// i 为索引,item为遍历值
});
});
补充:如果 ret 是一个字典,$.each 的参数有所不同,详见:http://api.jquery.com/jquery.each/
$.getJSON(
'ajax-get-a-dict'
,
function
(ret) {
$.each(ret,
function
(key, value){
// key 为字典的 key,value 为对应的值
});
});
最后,附上一个返回图片并显示的ajax实例:
代码下载:zqxt_ajax_pic.zip
CSRF(Cross-site request forgery跨站请求伪造,也被称为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
Django 中自带了 防止CSRF攻击的功能,但是一些新手不知道如何使用,给自己编程带来了麻烦。常常会出现下面django csrf token missing or incorrect的错误。
GET 请求不需要 CSRF 认证,POST 请求需要正确认证才能得到正确的返回结果。一般在POST表单中加入 {% csrf_token %}
<
form
method
=
"POST"
action
=
"/post-url/"
>
{% csrf_token %}
<
input
name
=
'zqxt'
value
=
"自强学堂学习Django技术"
>
</
form
>
如果使用Ajax调用的时候,就要麻烦一些。需要注意以下几点:
在视图中使用 render (而不要使用 render_to_response)
使用 jQuery 的 ajax 或者 post 之前 加入这个 js 代码:http://www.ziqiangxuetang.com/media/django/csrf.js
jQuery(document).ajaxSend(
function
(event, xhr, settings) {
function
getCookie(name) {
var
cookieValue =
null
;
if
(document.cookie && document.cookie !=
''
) {
var
cookies = document.cookie.split(
';'
);
for
(
var
i = 0; i < cookies.length; i++) {
var
cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if
(cookie.substring(0, name.length + 1) == (name +
'='
)) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break
;
}
}
}
return
cookieValue;
}
function
sameOrigin(url) {
// url could be relative or scheme relative or absolute
var
host = document.location.host;
// host + port
var
protocol = document.location.protocol;
var
sr_origin =
'//'
+ host;
var
origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return
(url == origin || url.slice(0, origin.length + 1) == origin +
'/'
) ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin +
'/'
) ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
function
safeMethod(method) {
return
(/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
if
(!safeMethod(settings.type) && sameOrigin(settings.url)) {
xhr.setRequestHeader(
"X-CSRFToken"
, getCookie('csrftoken'));
}
});
或者 更为优雅简洁的代码(不能写在 .js 中,要直接写在模板文件中):
$.ajaxSetup({
data: {csrfmiddlewaretoken:
'{{ csrf_token }}'
},
});
这样之后,就可以像原来一样的使用 jQuery.ajax() 和 jQuery.post()了
最后,附上一个 Django Ajax CSRF 实例:exam.zip
- ajax缓存与session
- Session与Ajax
- PHP+jQuery+Ajax+SESSION登录与退出
- ajax session
- 关于 验证码 Ajax,jQuery,Cookie与Session 总结
- AJAX and Session
- Ajax里面用Session
- Ajax读写Session值
- Ajax Session Management Timer
- Ajax Session Management Timer
- Ajax中session使用
- ajax给session赋值
- ajax给session赋值
- cookie,session 和AJAX
- Ajax使用session但是
- Ajax--request,session
- html ajax 跨域session
- Ajax请求session过期解决
- SVN—patch的应用(create patch,apply patch)
- 现在的我面临毕业,难道还能继续啥也不会吗?致未来的软件工程师
- sql 2008 远程过程调用失败 0x800706be
- win7 postman 创建快捷方式
- Laboratory for Web Algorihmics数据集格式转换
- Session与Ajax
- 设计模式(Design Pattern)
- POJ 1046
- nginx之 [error] 6702#0:XXX is forbidden (13: Permission denied)
- Java:String、StringBuffer和StringBuilder的区别
- C语言作业-6-2完数
- hadoop-错误总结
- jq $.ajax POST/GET 向服务器传值问题
- Java之Spring框架入门示例!