request请求
http的请求主要使用POST和GET两种,GET直接把url写在地址栏里访问,而POST可以直接发送信息并可以发送文件。如果页面不需要跳转,只是给后端发送信息,务必使用POST。
在一个HttpRequest对象中,GET和 POST属性是的实例django.http.QueryDict[1],类似于字典的类的类经过自定义以处理同一键的多个值,因为某些HTML表单元素尤其是<select multiple>为同一键传递多个值。
request的常用属性和方法
属性 | 说明 |
---|---|
HttpRequest.body | 原始HTTP请求正文为字节串,而这个可以处理二进制图像,XML有效负载等。当前端使用Ajax,data = json.loads(r.body) 可以解析JSON数据,data作为字典使用。 |
HttpRequest.scheme | 代表请求的协议,http或者https |
HttpRequest.path | 一个字符串,代表所请求页面的完整路径,不带参数,不包括协议名或域名。例: "/music/bands/the_beatles/" |
HttpRequest.method | 一个字符串,代表请求中使用的HTTP方法。保证是大写的。 |
HttpRequest.COOKIES | 包含所有cookie的字典。键和值是字符串。 |
HttpRequest.GET | 包含所有给定HTTP GET参数的类字典对象 |
HttpRequest.POST | 普通用法与GET类似,只是url不显示在浏览器地址栏。可以用带有空POST字典的POST发出请求(比如文件上传),因此应使用if r.POST: 而不是if request.method == "POST":
|
HttpRequest.FILES | 包含所有上载文件的类字典对象。是通过post方式发送的,但发送普通post请求时,r.FILES是空白的。关于文件,详见下一节 |
HttpRequest.META | 包含所有可用HTTP标头的字典[2]。常用:r.META['HTTP_HOST'] -客户端发送的HTTP Host标头,网站的域名或IP;r.META['REMOTE_ADDR'] -客户端的IP地址。 |
HttpRequest.headers | 不区分大小写,也不区分横线下划线,类似于dict的对象,该对象提供对请求中所有HTTP前缀的标头(plus Content-Length和Content-Type)的访问。包含浏览器和设备信息request.headers['User-Agent']:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)
|
方法 | 功能 |
---|---|
HttpRequest.get_host() | 返回请求的原始主机,获取客户端请求的服务器地址。类似于r.META['HTTP_HOST']
|
HttpRequest.is_ajax() | 通过检查字符串的标头,判断是否通过XMLHttpRequest发送请求 |
GET
Django的理念不喜欢在地址栏中写很长很复杂的url:[3]
在你上网的过程中,很可能看见过像这样美丽的 URL:
ME2/Sites/dirmod.asp?sid=&type=gen&mod=Core+Pages&gid=A6CD4967199A42D9B65B1B
。别担心,Django 里的 URL 规则 要比这优雅的多!
所以GET也只用来做一些简单的工作(翻页等),而不做会让数据库发生改变的功能。但是为了方便举例,这里有一个直观的修改数据库的代码片段,POST的用法类似:
def daka(request):
id = -1
if request.method == 'GET':
rg = request.GET
cs = ClkSign(
nikeName=rg['nikeName'],
name=rg['name'],
userId=rg['userId'],
locaAdd=rg['locaAdd'],
locatude=rg['locatude'],
dev_locatude=rg['dev_locatude'],
datetime=timezone.now()
)
cs.save()
id = cs.id
return JsonResponse({'code': 1, '_id': id})
GET请求只包含字符串信息。通过request.method == 'GET'
来判断是GET请求后,用request.GET
就能获取携带信息的QueryDict
,用法与字典类似。
并且,GET有长度限制,不同浏览器会有不同,但最多也只有8KB。而POST信息的长度限制是2GB,一般情况下足以满足需要。[4]
POST
POST的使用与GET很相似,但POST可以发送大文件,并且为了方式跨域,需要考虑csrf。
csrf
django为了安全起见,默认使用csrf,本服务器自身提供的网页只有写明csrf才能发送POST请求:[5]
1、不推荐禁用掉django中的CSRF。
2、我们可以再html页面的form表单中添加csrf_token,带着表单的请求一起发送到服务器去验证><form enctype="multipart/form-data" method="post" action="{% url 'new_article' %}"> {% csrf_token %}
3、在后端一定要使用render()的方法返回数据。
return render(request, 'article_new.html', {'article_list': article_list}) ```
其他网站的网页或者微信小程序若想向Django请求POST,在setting中要注释掉应用列表中的中间件django.middleware.csrf.CsrfViewMiddleware
:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
这样DJango就不再做csrf验证了。
Ajax
request.body
处理前端用Ajax发来的json对象,存为一个字典,典型用法如下所示:
import json
def detail(r):
data = json.loads(r.body)
id = data['id']
JsonResponse[6]
典型用法如下所示:
>>> from django.http import JsonResponse
>>> response = JsonResponse({'foo': 'bar'})
>>> response.content
b'{"foo": "bar"}'
>>>return response
如果序列化非字典对象,您必须将safe
参数设置为False
:
>>> return JsonResponse([1, 2, 3], safe=False)
如果不写safe=False
,会报错。这个safe主要是为了照顾老版本浏览器的兼容性。
HttpResponse
如果只需发送一个字符串类型的值,也不需要键名,使用HttpResponse
更简单。
from django.http import HttpResponse
# ...
return HttpResponse('success')