请求HttpRequest

提示:

  • 用户发送请求时携带的参数后端需要使用,而不同的发送参数的方式对应了不同的提取参数的方式
  • 所以要学会如何提取参数,我们就需要先了解前端传参数有哪些方式

回想一下,利用HTTP协议向服务器传参有几种途径?

  • 查询字符串数据(query string):

    • 形如:?key1=value1&key2=value2
    • 比如:http://www.meiduo.site/list/115/1/?sort=price中的?sort=price
  • 请求体数据(body):
    • 比如:表单数据、json、......
  • URL路径中的特定部分数据:
    • 比如:http://www.meiduo.site/detail/2/中的/2/
    • 请求地址中的该部分数据,可以在路由中使用正则表达式提取出来
  • 请求头数据:
    • HTTP请求报文中的请求头数据(header)

为了演示请求和响应,我们会新建一个子应用request_response去演示相关内容

1. 提取查询字符串数据

提示:

  • 获取请求路径中的查询字符串参数,形如:?k1=v1&k2=v2
  • 可以通过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))

重要提示:

  • 提取查询字符串参数不区分请求方式,即使客户端进行POST方式的请求,依然可以通过request.GET获取请求中的查询字符串参数。

QueryDict补充:

  • QueryDict是由Django自己封装的一个数据类型,继承自python的字典Dict
  • 它被定义在django.http.QueryDict
  • 它专门用来存储请求中提取的查询字符串参数和请求体参数
    • 即,HttpRequest对象中的属性GET、POST都是QueryDict类型的数据
  • QueryDict的使用:
    # 如果键不存在则返回None值,可以设置默认值进行后续处理
    query_dict.get('键',默认值)
    # 可简写为:
    query_dict['键']

2. 提取请求体数据

提示:

  • 可以发送请求体数据的请求方式有:POST、PUT、PATCH、DELETE
  • 请求体数据格式不固定,常见的有:表单类型数据和JSON字符串类型,我们应区别对待

2.1 表单类型请求体数据(Form Data)

前端发送的表单类型的请求体数据,可以通过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表单发送的请求体数据

2.2 非表单类型请求体数据(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))

3. URL路径参数:提取URL路径中的特定部分数据

提示:

  • 在定义路由时,可以从URL中获取特定部分的路径参数
  • Django的路由系统会将提取的路径参数传递到视图的内部
  • path()和re_path()都可以提取路径参数

需求:

  • 需求1:http://127.0.0.1:8000/url_param1/18/

    • 提取路径中的数字18
  • 需求2:http://127.0.0.1:8000/url_param2/18500001111/
    • 提取路径中的手机号18500001111

3.1 path()提取路径参数

实现需求1

# 测试path()提取普通路径参数:http://127.0.0.1:8000/url_param1/18/
path('url_param1//', 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)

重要提示:

  • 路由中提取路径参数时,使用的关键字,必须跟视图中参数名一致

思考:

  • 实现需求1时提取age数字的是什么?

结论:

  • 路由转换器
  • Django默认封装了一些正则表达式,用于在path()中要提取路径参数时使用

默认的路由转换器:

  • 位置在django.urls.converters.py
DEFAULT_CONVERTERS = {
'int': IntConverter(), # 匹配正整数,包含0
'path': PathConverter(), # 匹配任何非空字符串,包含了路径分隔符
'slug': SlugConverter(), # 匹配字母、数字以及横杠、下划线组成的字符串
'str': StringConverter(), # 匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
'uuid': UUIDConverter(), # 匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00
}

实现需求2

  • http://127.0.0.1:8000/url_param2/18500001111/

    • 提取路径中的手机号18500001111

问题:

  • 默认的路由转换器中,没有专门用来匹配手机号的路由转换器
  • 所以在使用path()实现需求2时,就无法直接使用默认的路由转换器

解决方案:

  • 如果默认的路由转换器无法满足需求时,我们就需要自定义路由转换器

实现需求2:自定义路由转换器

  • 在任意可以被导入的python文件中,都可以自定义路由转换器
  • 比如:在工程根目录下,新建converters.py文件,用于自定义路由转换器

    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)

3.2 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)

3.3 path()和re_path()如何选择?

  • path()语法相对简洁一些,如果没有路径参数要提取或者要提取的路径参数可以使用默认的路由转换器实现时,就选择path()。
  • re_path()语法相对复杂一些,但是,如果希望在匹配路由时,由自己编写所有的正则表达式,就选择re_path()。
  • 需要注意的是,在使用re_path()时,网络地址正则表达式一定要写完整,要有严格的开头和结尾

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')

5. 其他常用HttpRequest对象属性

  • method:一个字符串,表示请求使用的HTTP方法,常用值包括:'GET'、'POST'。
  • FILES:一个类似于字典的对象,包含所有的上传文件。
  • COOKIES:一个字符串,包含了浏览器自动发送的cookie缓存数据。
  • user:请求中认证出来的用户对象。

HTTP请求向服务器传参方式的更多相关文章

  1. Jmeter 接口测试-请求 Headers 与传参方式

    1.添加信息表头. 注意:1.使用Parameters时,Content-Type要么不传,要么传application/x-www-form-urlencoded,因为不传时默认值就是applica ...

  2. 使用HTTP协议向服务器传参的方式及django中获取参数的方式

    使用HTTP协议向服务器传参的四种方式 URL路径携带参数,形如/weather/beijing/2018; 查询字符串(query string),形如key1=value1&key2=va ...

  3. Web API中的传参方式

    在Restful风格的WebApi的里面,API服务的增删改查,分别对应着Http Method的Get / Post / Delete /Put,下面简单总结了Get / Post /Delete ...

  4. axios常见传参方式

    1:get请求 一般发送请求是这么写 axios.get('/user?id=12345&name=user') .then(function (res) { console.log(res) ...

  5. mock和axios常见的传参方式

    第一次接手项目,传参方式还有些吃力,因此做一下总结. 首先我们需要会看swagger中的接口.里面写了某个接口需要接收什么样的值,前端怎么传递这个值 在mock中的传参方式: mock中传参的方式有两 ...

  6. $router和$route的区别,路由跳转方式name 、 path 和传参方式params 、query的区别

    一.$router和$route的区别 $router : 是路由操作对象,只写对象$route : 路由信息对象,只读对象 例子://$router操作 路由跳转 this.$router.push ...

  7. scrapy post payload的坑及相关知识的补充【POST传参方式的说明及scrapy和requests实现】

    一.问题及解决: 在用scrapy发送post请求时,把发送方式弄错了. 本来应该是 application/x-www-form-urlencoded  弄成了application/json. 但 ...

  8. Vue Router路由导航及传参方式

    路由导航及传参方式 一.两种导航方式 ①:声明式导航 <router-link :to="..."> ②:编程式导航 router.push(...) 二.编程式导航参 ...

  9. angularjs简单实现$http.post(CORS)跨域及$http.post传参方式模拟jQuery.post

    1.开启angularjs的CORS支持 .config(function($httpProvider) { // CORS post跨域配置 $httpProvider.defaults.useXD ...

  10. react中的传参方式

    react是一个SPA模式,即组件嵌套租,在一个单页面的应用中组件间的数值传递是必不可少的,主要的传参方式大致有一下几种: 1,在挂载的地方给组件传参 ReactDOM.rander(<a na ...

随机推荐

  1. Redis的不同客户端对比

    Redis 官方推荐的 Java 客户端有Jedis.lettuce 和 Redisson 客户端 简介 优点 缺点 Jedis 提供了比较全面的 Redis 操作 Jedis 简单全面, 支持 pi ...

  2. VS2019使用gtest

    VS2019使用gtest GoogleTest测试框架介绍(一)_liitdar的博客-CSDN博客_goole test 术语 test/test case/test suit Meaning G ...

  3. 如何让公司内网ip映射到公网?

    其实这就是端口映射的技术,而端口映射至外网访问2种方法,今天我们来具体谈一谈. 公司内外网互通是网络技术运维人员经常需要面对的问题和需求场景,不管是疫情严重的当下,还是不在公司而又无法快速回公司却又急 ...

  4. 在platformio自动上传esp8266固件

    不想每次上传固件的时候手工点按钮,修改这个文件:C:\Users\你的登录名.platformio\platforms\espressif8266\builder\main.py 在319行UPLOA ...

  5. ubuntu-wireshark打开出现错误的问题

    The capture session could not be initiated on interface 'enp2s0' (You don't have permission to captu ...

  6. Matchmaker Server 像素流送配对服务器

  7. 移动端性能测试--CPU资源

    一.背景 在很多场景下我们去使用 App,可能会碰到手机会出现发热发烫的现象.这是因为 CPU 使用率过高.CPU 过于繁忙,会使得整个系统无法响应用户,整体性能降低,用户体验变得相当差,也容易引起 ...

  8. WPF 后台实现按数字键滚动DataGrid 当前选中项

    最近遇到个项目,设备上没有鼠标,界面为全屏的一个DataGrid,需要实现按小键盘的0和1让DataGrid的当前选中行进行上下滚动 起到重要参考的是:   https://blog.csdn.net ...

  9. [AGC043B] 123 Triangle

    个人思路: 首先,经过 \(1\) 轮就没有 \(3\) 了. 先考虑能否递推前 \(i\) 个数的答案,发现不行. 再考虑能否推出 \(i\) 个数的答案的计算公式,也发现不行. 然后就不会了. 正 ...

  10. Word02 领慧讲堂就业讲座office真题

    1.课程的讲解之前,先来对题目进行分析,首先需要在考生文件夹下,将Wrod素材.docx文件另存为Word.docx,后续操作均基于此文件,否则不得分. 2.这一步非常的简单,打开下载素材文件,在[文 ...