1.查询字符串
前端要把参数传给服务器,可以通过查询字符串的方式,即在资源路径后面加上一个?号,再拼接查询参数,例如http://localhost/XXXX/?name=pan&age=18
我们在一个子应用的视图函数写一个接收查询字符串的类,并且get()和post()方法都实现,因为不管使用哪种请求方式,都可以接收到查询参数
urls.py
from . import views
urlpatterns = [
path('request_info/', views.RequestInfo.as_view()),
]
views.py
from django.views import View
from django import http
# 接收查询字符串: http://localhost/XXXX/?name=pan&age=18
# 提取查询字符串参数不区分请求方式,即使客户端进行POST方式的请求,依然可以通过request.GET获取请求中的查询字符串参数。
class RequestInfo(View):
def get(self, request):
# 使用get()方法获取数据,若不存在该参数名,则可以设置默认值
# 需要注意的是,如果出现重复赋值,get()方法只会获取最后一个数值
name = request.GET.get('name', '小明')
age = request.GET.get('age', '0')
# 也可以直接使用键取值
# print(request.GET['age'])
# 也可以接收全部重复数值,例如下面的链接,age重复了 多次
# http://localhost:8000/request_info/?name=xiaohei&age=18&age=20&age=22
args = request.GET.getlist('age') # 接收全部age的数值,并且保存在一个列表
print(args)
return http.HttpResponse('姓名是%s,年龄是%s' % (name, age))
def post(self, request):
name = request.GET.get('name', '小明')
age = request.GET.get('age', '0')
return http.HttpResponse('姓名是%s,年龄是%s' % (name, age))
我们注册好子路由和主路由之后就可以正常获取到传递的参数了
2.URL路径参数
2.1 path()简单提取
除了使用?拼接字符串,路径也是可以传递参数的,例如http://localhost:8000/request_goods/22/33/,url最后的22和33就是两个参数,具体几个参数我们可以指定,并且可以指定参数名
urls.py
from django.urls import path, re_path
from . import views
urlpatterns = [
...
# <>内表示参数的名字,引用的时候也要用这参数名
path('request_goods/<page>/<gid>/', views.RequestGoods.as_view()),
# 也可以指定参数的类型,如int
# path('request_goods/<int:page>/<int:gid>/', views.RequestGoods.as_view()),
...
]
views.py
from django.views import View
from django import http
# 获取url携带的路径参数
# http://localhost:8000/request_goods/22/33/
class RequestGoods(View):
# 传入的两个参数page和gid要在路由表声明
def get(self, request, page, gid):
return http.HttpResponse('当前第%s页,第号%s商品' % (page, gid))
在路由列表里指定参数的时候是可以指定参数类型的,默认的有5种类型
默认的路由转换器:
DEFAULT_CONVERTERS = {
'int': IntConverter(), # 匹配正整数,包含0
'path': PathConverter(), # 匹配任何非空字符串,包含了路径分隔符
'slug': SlugConverter(), # 匹配字母、数字以及横杠、下划线组成的字符串
'str': StringConverter(), # 匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
'uuid': UUIDConverter(), # 匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00
}
如果觉得默认的路由转换还不够,可以自定义,但是因为比较麻烦,我们还是直接在路由时使用正则匹配吧
2.2 re_path()正则提取
我们可以在路由的时候从路径提取要传递的数据,使用re_path()函数进行匹配
urls.py
from django.urls import path, re_path
from . import views
urlpatterns = [
...
# <>内表示参数的名字,引用的时候也要用这参数名
path('request_goods/<page>/<gid>/', views.RequestGoods.as_view()),
# 使用正则匹配手机号,并且指定参数名
re_path(r'^request_phone/(?P<phone_num>1[3-9]\d{9})/$', views.ResponsePhoneNumber.as_view()),
...
]
注意:写正则的时候,1.使用^、$指定前后字符串,2.使用圆括号分组起别名
view.py
from django.views import View
from django import http
# http://localhost:8000/request_phone/13977778888/
class ResponsePhoneNumber(View):
# 这里的phone_num参数由路由时指定
def get(self, request, phone_num):
return http.HttpResponse('提取到的手机号是:%s' % phone_num)
3.接收请求体数据
3.1 接收表单数据
urls.py
from django.urls import path, re_path
from . import views
urlpatterns = [
...
path('formdata/', views.FormdataView.as_view()),
...
]
views.py
from django.views import View
from django import http
# 接收表单数据
class FormdataView(View):
# 注意,表单数据只能通过post获取
def post(self, request):
username = request.POST.get('username')
password = request.POST.get('password')
return http.HttpResponse('用户名是:%s,密码是:%s' % (username, password))
注意:
- 接收表单数据,只能通过post()方法处理
- 如果出现csrf中间件阻止,可以打开项目的settings.py找到MIDDLEWARE列表,把csrf那一项注释掉
3.2 接收非表单数据
客户端发送过来的如果不是表单数据,则会被保留最原始的格式,可以通过request.body属性获取到bytes类型的二进制数据
我们这里以json数据为例
urls.py
from django.urls import path, re_path
from . import views
urlpatterns = [
...
path('formbody/', views.Bodydata.as_view()),
]
views.py
from django.views import View
from django import http
import json
# 除了查询字符串和表单数据,其他的数据都会被保留原始数据
# 例如由前端发送过来的json数据
class Bodydata(View):
def post(self, request):
json_str = request.body
json_dic = json.loads(json_str) # 把字符串转换成对象
username = json_dic.get('username')
password = json_dic.get('password')
print(json_str)
return http.HttpResponse('通过非表单提交的数据,用户名:%s,密码: %s' % (username, password))
4.接收请求头数据
浏览器在请求服务器的时候会在请求头夹带数据,这些数据可以通过request.META属性获取到,我们可以通过键来取出对应的值,例如我们可以取出比较常用的
请求头 | 说明 |
---|---|
CONTENT_LENGTH | 请求头的字符串长度 |
CONTENT_TYPE | 请求体的MIME文件类型 |
HTTP_ACCEPT | 响应时可接受的类型 |
HTTP_HOST | 主机地址 |
HTTP_REFERER | 关联的地址 |
HTTP_USER_AGENT | 浏览器代理 |
浏览器发出的请求头也是键值对方式的,但是浏览器的键与Django取值的键是有些不一样的
如果想查看更多请求头的信息,可以把request.META打印出来看一下
除了以上这些比较常用的请求头数据之外,我们还可以发送自定义的键值对,在服务端使用get()方法接收即可,需要注意的是,键会发生变化,改成“HTTP_大写键”
views.py
from django.shortcuts import render
from django.views import View
from django.http import HttpResponse
import json
class FormdataView(View):
def post(self, request):
print('=' * 30)
print(request.POST.get('name'))
print('=' * 30)
return HttpResponse('提交表单')
def get(self, request):
# 取值的键发生变化,原有的键名变成大写,再加上“HTTP_”前缀
print(request.META.get('HTTP_NAME', '没有值'))
print(request.META.get('HTTP_PASSWORD', '没有值'))
return HttpResponse('非表单数据')
使用postman发送header键值对数据