django请求与响应
目录
一、请求Request
利用HTTP协议向服务器传参有几种途径
Django中的QueryDict对象
1> GET属性获取查询字符串Query String 参数
2> POST属性 获取请求体参数
3> META属性 获取请求头数据
4> 其他常用HttpRequest对象属性
二、响应Response
1> HttpResponse
3> JsonResponse
一、请求Request
-
利用HTTP协议向服务器传参有几种途径
- 路径传参: 提取URL的特定部分,如/weather/beijing/2018,可以在服务器端的路由中用正则表达式截取参数;
- 查询字符串传参: 查询字符串(query string),形如key1=value1&key2=value2;
- 请求体传参:请求体(body)中发送的数据,比如表单数据、json、xml;
- 请求头传参:在http报文的请求头(header)中传参。
-
Django中的
QueryDict
对象-
QueryDict
对象介绍QueryDict定义在django.http.QueryDict中; HttpRequest对象的属性GET、POST都是QueryDict类型的对象;与python字典不同,QueryDict类型的对象用来处理同一个键带有多个值的情况.
-
get()
方法根据键获取值, 如果一个键同时拥有多个值将获取最后一个值; 如果键不存在则返回None值,可以设置默认值进行后续处理
dict.get('键',默认值)
# 可简写为
dict['键']
-
getlist()
方法根据键获取值,值以列表返回,可以获取指定键的所有值; 如果键不存在则返回空列表[],可以设置默认值进行后续处理
dict.getlist('键',默认值)
-
-
1> GET属性获取查询字符串Query String 参数
-
GET
属性说明获取请求路径中的查询字符串参数(形如 ?k1=v1&k2=v2 ),可以通过request.GET属性获取,返回QueryDict对象。
注意: 查询字符串不区分请求方式,即使客户端进行POST方式的请求,依然可以通过request.GET获取请求中的查询字符串数据。
-
主路由 # 获取查询字符串路由 path('qs/', views.query_string), 视图 from django.http import HttpResponse from django.views.decorators.csrf import csrf_exempt # 免除csrf校验 @csrf_exempt def query_string(request): # 获取键对应的最后一个值 a = request.GET.get('a') b = request.GET.get('b') # 获取键对应的所有值 a_list = request.GET.getlist('a') print(f"a = {a}") print(f"b = {b}") print(f"a_list = {a_list}") return HttpResponse('query_string OK')
-
API
测试 Apipost软件下载:# 测试平台 ApiPost7
GET请求 http://127.0.0.1:8080/qs/?a=1&b=3&a=10
POST请求 http://127.0.0.1:8080/qs/?a=1&b=3&a=10
-
-
2> POST属性 获取请求体参数
请求体数据格式不固定,可以是表单类型字符串,可以是JSON字符串,也可以是XML字符串; 应区别对待。
支持发送 请求体数据 的请求方式有: POST、PUT、PATCH、DELETE。
Django默认开启了CSRF防护,会对上述请求方式进行CSRF防护验证,在测试时可以关闭CSRF防护机制;
关闭方法:
1. 在 settings.py 配置文件 MIDDLEWARE 参数项中注释掉CSRF中间件CsrfViewMiddleware 全局生效
2. 为视图函数单独添加 csrf_exempt装饰器 进行CSRF豁免
-
表单类型 Form Data
前端发送的表单类型的请求体数据,可以通过request.POST属性获取,返回QueryDict对象。
注意: request.POST只能用来获取POST方式的请求体表单数据。
说明: 请求头中 Content-Type 为multipart/form-data(多媒体表单) 或者 application/x-www-form-urlencoded(简单表单) 即为表单类型请求
-
主路由
# 获取表单数据路由
path('form/', views.get_form),
-
在
templates
模板文件夹中创建模版文件form.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户信息收集表</title> </head> <body> <form action="/form/" method="post" enctype="multipart/form-data"> <p> 用户名: <input type="text" name="user"> <br> </p> <p> 密 码: <input type="password" name="pwd"> <br> </p> <p> 爱 好: <input type="checkbox" name="hobby" value="game"> 游戏 <input type="checkbox" name="hobby" value="study"> 学习 </p> <p> 文件上传: <input type="file" name="file1"> </p> <p> <input type="submit" value="提交"> </p> </form> </body> </html>
-
视图
import os from django.http import HttpResponse from django.shortcuts import render from django.views.decorators.csrf import csrf_exempt # 导入配置对象 from django.conf import settings @csrf_exempt def get_form(request): # 处理get请求 返回表单页面 if request.method == "GET": return render(request, "form.html") # 处理post请求 接收表单数据 user = request.POST.get("user") pwd = request.POST.get("pwd") hobby = request.POST.getlist("hobby") upload_file = request.FILES.get("file1") print(f"user: {user}") print(f"pwd: {pwd}") print(f"hobby: {hobby}") if upload_file: file_save_path = os.path.join(settings.MEDIA_ROOT, upload_file.name) with open(file_save_path, "wb") as wf: # 分块写入文件数据 for chunk in upload_file.chunks(): wf.write(chunk) return HttpResponse('get_form OK')
配置文件
settings.py
-
MEDIA_ROOT = os.path.join(BASE_DIR, 'upload_media')
测试
-
# 获取表单页面 GET http://127.0.0.1:8080/form/ # 填写表单并提交表单数据, 查看接收数据和文件
-
-
非表单类型 Non-Form Data
非表单类型的请求体数据Django无法自动解析,可以通过request.body属性获取最原始的请求体数据,自己按照请求体数据格式(JSON、XML等)进行解析。(注意:request.body返回bytes类型。)
例如: 要获取请求体中的如下JSON格式数据可以按如下步骤提取数据:
{"a": 1, "b": 2}
-
主路由
# 获取非表单数据路由 path('nonForm/', views.get_non_form),
-
视图
import json @csrf_exempt def get_non_form(request): json_str = request.body # python3.6 及以上版本无需执行解码操作,json.loads可以直接处理二进制数据 json_str = json_str.decode() req_data = json.loads(json_str) print(f"req_data = {req_data}") print(f"a = {req_data['a']}") print(f"b = {req_data['b']}") return HttpResponse('get_non_form OK')
测试
-
# 测试平台 ApiPost7
# 提交非表单数据(这里测试json数据)
POST http://127.0.0.1:8080/nonForm/
-
-
-
3> META属性 获取请求头数据
可以通过request.META属性获取请求头headers中的数据,request.META为字典类型。
-
常见的请求头如:
CONTENT_LENGTH
– 请求体长度.CONTENT_TYPE
– 内容的数据类型。同附加信息的查询一起使用,如 HTTP 查询 GET、 POST 和 PUT.HTTP_ACCEPT
– 浏览器支持的 MIME 类型.HTTP_ACCEPT_ENCODING
– 浏览器支持的压缩编码.HTTP_ACCEPT_LANGUAGE
– 浏览器支持的语言.HTTP_HOST
– 服务器端IP及端口.HTTP_REFERER
– 用于告知服务器是从哪个页面链接过来的.HTTP_USER_AGENT
– 使用的用户代理 域名.QUERY_STRING
– 查询解析输入并在运算符周围分割文本.REMOTE_ADDR
– 客户端IP.REMOTE_HOST
– 发出请求的主机名称。如果服务器无此信息,它将设置为空的 MOTE_ADDR 变量.REMOTE_USER
– 服务器认证后的用户.REQUEST_METHOD
– 该方法用于提出请求。相当于用于 HTTP 的 GET、HEAD、POST 等等.SERVER_NAME
– 出现在自引用 UAL 中的服务器主机名、DNS 化名或 IP 地址.SERVER_PORT
– 发送请求的端口号.
-
具体使用:
-
主路由
# 获取请求头数据路由 path('header/', views.get_request_header),
-
视图
@csrf_exempt def get_request_header(request): meta = request.META print(f"请求体长度: {meta['CONTENT_LENGTH']}") print(f"服务器端IP及端口: {meta['HTTP_HOST']}") print(f"内容的数据类型: {meta['CONTENT_TYPE']}") print("\nHttpRequest的其他对象属性:") print(f"请求方法: {request.method}") print(f"用户对象: {request.user}") print(f"完整路径: {request.path}") print(f"提交的数据的编码方式: {request.encoding}") print(f"coolies: {request.COOKIES}") print(f"session: {request.session}") print(f"是否为ajax请求: {request.is_ajax()}") return HttpResponse('get_request_header OK')
-
测试
# 测试平台 ApiPost7
GET http://127.0.0.1:8080/header/
POST http://127.0.0.1:8080/header/
-
-
-
4> 其他常用HttpRequest对象属性
-
method
:一个字符串,表示请求使用的HTTP方法,常用值包括:'GET'、'POST'。 -
user
:请求的用户对象。 -
path
:一个字符串,表示请求的页面的完整路径,不包含域名和参数部分。 -
get_full_path()
: 获取请求的页面的完整路径,不包含域名但是包含查询参数部分。 -
encoding
:一个字符串,表示提交的数据的编码方式。- 如果为None则表示使用浏览器的默认设置,一般为utf-8。
- 这个属性是可写的,可以通过修改它来修改访问表单数据使用的编码,接下来对属性的任何访问将使用新的encoding值。
-
GET
: 一个类似于字典的对象,包含get请求方式的所有参数 -
POST
: 一个类似于字典的对象,包含post请求方式的所有参数 -
FILES
:一个类似于字典的对象,包含所有的上传文件。 -
COOKIES
: 一个标准的Python字典,包含所有的cookie,键和值都为字符串 -
session
: 一个既可读又可写的类似于字典的对象,表示当前的会话,只有当Django启用会话的支持时才可用 -
is_ajax( )
: 如果请求是通过XMLHttpRequest发起的,则返回True -
resolver_match
: 当前路由匹配成功的路由对象(url_name属性可以得到当前匹配到的路由名)
-
二、响应Response
视图在接收请求并处理后,必须返回HttpResponse对象或子对象。HttpRequest对象由Django创建,HttpResponse对象由开发人员创建。
-
1>
HttpResponse
-
可以使用
django.http.HttpResponse
来构造响应对象。HttpResponse(content=响应体, content_type=响应体数据类型, status=状态码)
-
也可通过
HttpResponse
对象属性来设置响应体、状态码:content
:表示返回的内容。status_code
:返回的HTTP响应状态码。charset
:表示response
采用的编码字符集,字符串类型
-
可以直接将
HttpResponse
对象当做字典,使用键值对赋值的方式设置响应头信息:response = HttpResponse()
# 自定义响应头 Platform, 值为xx
response['Platform'] = 'xx'
-
使用示例:
-
主路由
# 设置响应路由 path('response/', views.set_response),
-
视图
@csrf_exempt def set_response(request): # 通过 HttpResponse 构造响应对象 # return HttpResponse(content='xxxx', status=200) # 通过 HttpResponse 对象属性设置响应体、状态码、响应头 response = HttpResponse() response.content = 'xxxx' response.status_code = 200 response['Platform'] = 'xx return response
-
测试
# 测试平台 ApiPost7
POST http://127.0.0.1:8080/response/2> HttpResponse 的子类
-
-
-
-
Django提供了一系列HttpResponse的子类,可以快速设置状态码
HttpResponseRedirect
301HttpResponsePermanentRedirect
302HttpResponseNotModified
304HttpResponseBadRequest
400HttpResponseNotFound
404HttpResponseForbidden
403HttpResponseNotAllowed
405HttpResponseGone
410HttpResponseServerError
500
-
-
3>
JsonResponse
-
若要返回
json
数据,可以使用JsonResponse
来构造响应对象,作用:-
帮助我们将数据转换为
json
字符串 -
设置响应头
Content-Type
为application/json
from django.http import JsonResponse def demo_view(request): return JsonResponse({'城市': 'beijing', 'subject': 'python'}, json_dumps_params={'ensure_ascii': False})
-
-