Django基础之httprequest请求、响应、中间件
1.请求HttpRequest
- 用户发送请求时携带的参数后端需要使用,而不同的发送参数的方式对应了不同的提取参数的方式
-
前端传递参数的四种方式:
1.查询字符串数据(querystring)?key1=value1&key2=value2
2.请求体数据(body)表单数据、json...
3.URL路径中特定部分数据http://www.meiduo.site/detail/2/
中的/2/
4.请求头数据
http请求保温中的请求头数据(header)
1.1. 提取查询字符串数据
-
通过
request.GET
属性获取,并返回QueryDict类型的对象# 注册总路由 urlpatterns = [ # 用户模块:http://127.0.0.1:8000/users/register/ path('', include('users.urls')), # 请求和响应 path('', include('request_response.urls')), ]
# 注册子路由 urlpatterns = [ # 测试提取查询字符串参数:http://127.0.0.1:8000/querystring/?name=zxc&age=18 path('querystring/', views.QSParamView.as_view()), ]
class QSParamView(View): """测试提取查询字符串参数 http://127.0.0.1:8000/querystring/?name=zxc&age=18 """ def get(self, request): # 获取查询字符串参数name、age name = request.GET.get('name', '小明') age = request.GET.get('age', '0') return http.HttpResponse('查询字符串参数:%s--%s' % (name, age))
说明:
1.提取查询字符串参数不区分请求方式,即使客户端进行POST
方式的请求,依然可以通过request.GET
获取请求中的查询字符串参数。
2.querydict补充:- QueryDict是由Django自己封装的一个数据类型,继承自python的字典Dict
- 它被定义在django.http.QueryDict中
-
专门用来存储请求中提取的查询字符串参数和请求体参数
HttpRequest
对象中的属性GET、POST
都是QueryDict类型的数据 -
QueryDict
的使用:# 如果键不存在则返回None值,可以设置默认值进行后续处理 query_dict.get('键',默认值) # 可简写为: query_dict['键']
1.2.提取请求体数据
-
可以发送请求体数据的请求方式有:
POST、PUT、PATCH、DELETE
- 请求体数据格式不固定,常见的有:表单类型数据和JSON字符串类型
-
表单类型请求体数据(FormData)
前端发送的表单类型的请求体数据,可以通过request.POST
属性获取,并返回QueryDict
对象。# 测试提取表单类型请求体数据:http://127.0.0.1:8000/formdata/ path('formdata/', views.FormDataParamView.as_view()), ################################################### class FormDataParamView(View): """测试提取表单类型请求体参数 http://127.0.0.1:8000/formdata/ """ def post(self, request): # 获取表单类型请求体参数中的username、password username = request.POST.get('username') password = request.POST.get('password') return http.HttpResponse('表单类型请求体参数:%s--%s' % (username, password))
注意:request.POST只能用来获取POST表单发送的请求体数据
-
非表单类型请求体数据(Non-Form Data):JSON
-
非表单类型的请求体数据,Django无法自动解析,可以通过
request.body
属性获取最原始的请求体数据 - 然后自己按照具体请求体原始数据的格式(JSON等)进行解析
-
request.body
获取的是bytes类型的请求体原始数据
需求:
获取请求体中的JSON数据{ "username": "张小厨", "password": "123" }
可以进行如下操作:
# 测试提取非表单类型请求体参数:http://127.0.0.1:8000/json/ path('json/', views.JSONParamView.as_view()),
import json class JSONParamView(View): """测试提取非表单类型请求体参数 http://127.0.0.1:8000/json/ """ def post(self, request): # 获取请求体中原始的JSON数据 json_str = request.body # 使用json模块将原始的JSON数据转字典 json_dict = json.loads(json_str) # 提取JSON数据中的参数 username = json_dict.get('username') password = json_dict.get('password') return http.HttpResponse('非表单类型请求体参数:%s--%s' % (username, password))
-
非表单类型的请求体数据,Django无法自动解析,可以通过
1.3.URL路径参数:提取URL路径中特定部分数据
-
Django的路由系统会将提取的路径参数传递到视图的内部
-
path()和re_path()都可以提取路径参数
-
路由转换器
Django默认封装了一些正则表达式,用于在path()中提取参数使用DEFAULT_CONVERTERS = { 'int': IntConverter(), # 匹配正整数,包含0 'path': PathConverter(), # 匹配任何非空字符串,包含了路径分隔符 'slug': SlugConverter(), # 匹配字母、数字以及横杠、下划线组成的字符串 'str': StringConverter(), # 匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式 'uuid': UUIDConverter(), # 匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00 }
-
自定义路由转换器
在任意可以被导入的python文件中,都可以自定义路由转换器class MobileConverter: """自定义路由转换器:匹配手机号""" # 匹配手机号码的正则 regex = '1[3-9]\d{9}' def to_python(self, value): # 将匹配结果传递到视图内部时使用 return int(value) def to_url(self, value): # 将匹配结果用于反向解析传值时使用 return str(value)
注册自定义路由转换器
# 在总路由中,注册自定义路由转换器 from django.urls import register_converter from converters import MobileConverter # 注册自定义路由转换器 # register_converter(自定义路由转换器, '别名') register_converter(MobileConverter, 'mobile') urlpatterns = []
使用自定义路由转换器
# 测试path()中自定义路由转换器提取路径参数:手机号 http://127.0.0.1:8000/url_param2/18500001111/ path('url_param2/<mobile:phone_num>/', views.URLParam2View.as_view()),
class URLParam2View(View): """测试path()中自定义路由转换器提取路径参数:手机号 http://127.0.0.1:8000/url_param2/18500001111/ """ def get(self, request, phone_num): """ :param phone_num: 路由提取的关键字参数 """ return http.HttpResponse('测试path()提取路径参数手机号:%s' % phone_num)
-
path()提取路径参数
# 测试path()提取普通路径参数:http://127.0.0.1:8000/url_param1/18/ path('url_param1/<int:age>/', views.URLParam1View.as_view()),
class URLParam1View(View): """测试path()提取普通路径参数 http://127.0.0.1:8000/url_param1/18/ """ def get(self, request, age): """ :param age: 路由提取的关键字参数 """ return http.HttpResponse('测试path()提取普通路径参数:%s' % age)
注意:路由中提取路径参数时,使用的关键字,必须跟视图中参数名一致
-
re_path()提取路径参数
# 测试re_path()提取路径参数:http://127.0.0.1:8000/url_param3/18500001111/ re_path(r'^url_param3/(?P<phone_num>1[3-9]\d{9})/$', views.URLParam3View.as_view()),
class URLParam3View(View): """测试re_path()提取路径参数 http://127.0.0.1:8000/url_param3/18500001111/ """ def get(self, request, phone_num): """ :param phone_num: 路由提取的关键字参数 """ return http.HttpResponse('测试re_path()提取路径参数:%s' % phone_num)
-
path()和re_path()选择原则:
1.path()语法相对简洁一些,如果没有路径参数要提取或者要提取的路径参数可以使用默认的路由转换器实现时,就选择path()
2.re_path()语法相对复杂一些,但是,如果希望在匹配路由时,由自己编写所有的正则表达式,就选择re_path()
3.需要注意的是,在使用re_path()时,网络地址正则表达式一定要写完整,要有严格的开头和结尾
1.4.请求头
-
可以通过
request.META
属性获取请求头headers中的数据,request.META
为字典类型
常见的请求头:
- CONTENT_LENGTH – The length of the request body (as a string).
- CONTENT_TYPE – The MIME type of the request body.
- HTTP_ACCEPT – Acceptable content types for the response.
- HTTP_ACCEPT_ENCODING – Acceptable encodings for the response.
- HTTP_ACCEPT_LANGUAGE – Acceptable languages for the response.
- HTTP_HOST – The HTTP Host header sent by the client.
- HTTP_REFERER – The referring page, if any.
- HTTP_USER_AGENT – The client’s user-agent string.
- QUERY_STRING – The query string, as a single (unparsed) string.
- REMOTE_ADDR – The IP address of the client.
- REMOTE_HOST – The hostname of the client.
- REMOTE_USER – The user authenticated by the Web server, if any.
- REQUEST_METHOD – A string such as “GET” or “POST”.
- SERVER_NAME – The hostname of the server.
- SERVER_PORT – The port of the server (as a string).
使用:
class HeadersParamView(View): """测试提取请求头参数""" def get(self, request): # 获取请求头中文件的类型 ret = request.META.get('CONTENT_TYPE') return http.HttpResponse('OK')
1.5.其他常用的HttpRequest对象属性
- method:一个字符串,表示请求使用的HTTP方法,常用值包括:‘GET’、‘POST’
- FILES:一个类似于字典的对象,包含所有的上传文件
- COOKIES:一个字符串,包含了浏览器自动发送的cookie缓存数据
- user:请求中认证出来的用户对象
2.响应HttpResponse
- 视图在接收请求并处理后,必须返回HttpResponse对象或子对象
- HttpRequest对象由Django创建,HttpResponse对象或子对象由开发人员创建
-
常见的响应方式:
1.HttpResponse()
:响应多种数据类型
2.JsonResponse()
:响应JSON
3.redirect()
:重定向
4.render()
:渲染并响应HTML模板
2.1.HttpResponse
-
使用
django.http.HttpResponse
来构造响应对象
response = HttpResponse(content=响应体, content_type=响应体数据类型,默认为text/html, status=状态码,默认为200)
-
补充:
HttpResponse
子类
1.HttpResponseRedirect
默认响应状态码为 301
2.HttpResponsePermanentRedirect
默认响应状态码为 302
3.HttpResponseNotModified
默认响应状态码为 304
4.HttpResponseBadRequest
默认响应状态码为 400
5.HttpResponseNotFound
默认响应状态码为 404
6.HttpResponseForbidden
默认响应状态码为 403
7.HttpResponseNotAllowed
默认响应状态码为 405
8.HttpResponseGone
默认响应状态码为 410
9.HttpResponseServerError
默认响应状态码为 500
2.2.JsonResponse:响应JSON
-
JsonResponse
作用:
1.帮助我们将响应的数据转换为JSON字符串
2.设置响应头Content-Type为 application/json
2.3.redirect():重定向
-
redirect()
:重定向-
()内的路径左右必须要有
/
-
()内的路径左右必须要有
-
redirect()重定向 搭配 反向解析
- 问题:定义的路由地址在迭代更新时会变化,导致需要手动修改变化的地址
- 需求:保证在版本迭代时,使用了新设计的地址替换路由中原有的地址,不用手动去修改,达到动态获取的目的
-
路由反解析:
使用路由的别名,动态解析出该路由的真实地址
总路由中给自引用·子应用的总路由起别名
urlpatterns = [ # 请求和响应 # path('', include(('子路由', '子应用名字'), namespace='总路由别名,可以随便命名')), path('', include(('request_response.urls', 'request_response'), namespace='request_response')), ]
子路由中给子应用的子路由起别名
# 测试重定向 path('login_redirect/', views.LoginRedirectView.as_view()), path('index/', views.IndexView.as_view(), name='index'),
视图中,使用路由的别名,动态的解析出该路由中的真实地址
from django.shortcuts import render, redirect, reverse class IndexView(View): """测试重定向
http://127.0.0.1:8000/index/
""" def get(self, request): return http.HttpResponse('假装这是个网站首页') class LoginRedirectView(View): """测试重定向
http://127.0.0.1:8000/login_redirect/
""" def post(self, request): # 假装正在处理登录逻辑 # 假装登录逻辑处理完成 # ...... # 将用户通过重定向引导到首页 # return redirect('/index/') # ret_url = reverse('总路由别名:子路由别名') ret_url = reverse('request_response:index') return redirect(ret_url)
3.中间件
3.1.介绍
- Django中的中间件是一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出
- 中间件的设计为开发者提供了一种无侵入式的开发方式,增强了Django框架的健壮性,其它的MVC框架也有这个功能
使用场景:
- 当某些操作在每次请求或响应时都会执行时,可以写在中间件中
- 比如,每次发送post请求都要进行CSRF验证,就把CSRF验证的代码写在中间件中
设计思想:
- 面向切面编程、无侵害式编程
-
不用直接修改框架源码,就可以达到自己想要的执行结果
默认中间件
# 中间件 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 为保证非GET请求(POST, PUT, DELETE)可以正常接收,该中间件需要注释掉 # 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
3.2.中间件方法
Django在中间件中预置了六个方法,这六个方法会在不同的阶段自动执行,对输入或输出进行干预
-
初始化方法
启动Django程序,初始化中间件时,自动调用一次,用于确定是否启用当前中间件def __init__(self, get_response=None): pass
-
处理请求前的方法:(重要)
在处理每个请求前,自动调用,返回None或HttpResponse对象def process_request(self, request): pass
-
处理视图前的方法:(重要)
在处理每个视图前,自动调用,返回None或HttpResponse对象def process_view(self, request, view_func, view_args, view_kwargs): pass
-
处理模板响应前的方法
在处理每个模板响应前,自动调用,返回实现了render方法的响应对象def process_template_response(self, request, response): pass
-
处理响应后的方法:(重要)
在每个响应返回给客户端之前,自动调用,返回HttpResponse对象def process_response(self, request, response): pass
-
异常处理
当视图抛出异常时,自动调用,返回一个HttpResponse对象def process_exception(self, request,exception): pass
3.3.自定义中间件
- 中间件是一个独立的Python类,可以定义Django提供的六个方法中的一个或多个
- 在工程根目录下,新建middlewares.py文件来自定义中间件
- 在自定义的中间件中,会实现最重要的三个方法
# 导入中间件的父类 from django.utils.deprecation import MiddlewareMixin class TestMiddleware1(MiddlewareMixin): """自定义中间件""" def process_request(self, request): """处理请求前自动调用""" print('process_request1 被调用') def process_view(self, request, view_func, view_args, view_kwargs): # 处理视图前自动调用 print('process_view1 被调用') def process_response(self, request, response): """在每个响应返回给客户端之前自动调用""" print('process_response1 被调用') return response
注册自定义的中间件
# 中间件 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 为保证非GET请求(POST, PUT, DELETE)可以正常接收,该中间件需要注释掉 # 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'middlewares.TestMiddleware1', # 注册自定义的中间件1 ]
3.4.中间件执行顺序
- 在视图被处理前(输入),中间件由上至下依次执行
-
在视图被处理后(输出),中间件由下至上依次执行
本文地址:https://blog.csdn.net/yyyyyyyyyjjj/article/details/108267905