django为了帮助应对跨站脚本攻击,在以POST方法提交表单时,要求将其内置的CSRF中间件添加到setting.py的中间件设置中(django.middleware.csrf.CsrfViewMiddleware,默认已添加),并且在<form>标签后添加{% csrf_token %},即表单元素变为:
<form action="" method="post">{% csrf_token %}
同时,表单提交对应的视图函数也要调用RequestContext生成context实例,用于生成响应。这样才能顺利提交表单。
根据官方文档内容(https://docs.djangoproject.com/en/1.11/ref/csrf/),如果使用render()快捷方法、generic view或contrib,那就不用特意设置RequestContext,因为它们默认已经在使用RequestContext了。因此,提交表单的视图函数可以这样写
from django.shortcuts import render def receiving_data(req): if req.method == ‘POST‘: #your code ctx = {‘key‘: ‘foo‘} return render(req, ‘site/xx.html‘, ctx)
后来又看了官方文档后(https://docs.djangoproject.com/en/1.11/ref/templates/api/#django.template.RequestContext)联想能不能用 t = loader.get_template(‘foo.html‘) 的形式加载template,用RequestContext生成context实例,再用 return HttpResponse(t.render(context)) 生成响应。
经过测试后,发现不行,错误为“context must be a dict rather than RequestContext.”。
根据官方文档(https://docs.djangoproject.com/en/1.11/topics/templates/#django.template.loader.get_template)
可知Template.render(context=None, request=None)这个函数中,context必须是一个dict。而我们之前提供的RequestContext并不是dict,自然就无法使用RequestContext的实例作为Template.render()的context的值了。
后来又查到django1.11的更新日志,对loader.get_template()又有一些说明,内容如下:
(https://docs.djangoproject.com/en/dev/releases/1.11)
For compatibility with multiple template engines, django.template.backends.django.Template.render() (returned from high-level template loader APIs such as loader.get_template()) must receive a dictionary of context rather than Context or RequestContext. If you were passing either of the two classes, pass a dictionary instead – doing so is backwards-compatible with older versions of Django.
原来在1.11版中,loader.get_template()不再支持以Context 或RequestContext.实例作为context参数的值。
PS:官方文档这一段
(https://docs.djangoproject.com/en/1.11/ref/templates/api/#django.template.RequestContext)中,
可以发现django.template.Template的实例依然可以用django.template.Context的实例作为context参数,具体还有待研究。