一:前端传输参数的4种方式:
1:查询字符串的方式:
http://www.meiduo.site/list/115/1/?sort=price 中的?sort=price
2:请求体数据:
例如:表单,json
3:url路径的部分:
http://www.meiduo.site/detail/2/中的/2/
4:请求头数据:以键值对的方式存储。
二:提取查询字符串数据
获取请求路径中的查询字符串参数,形如:?k1=v1&k2=v2
可以通过request.GET属性获取,并返回QueryDict类型的对象
1:首先在视图中创建类来接收request,然后使用
request.GET.get(‘name’, ‘小明’)获取字符串中的数据和指定默认值。
class QSParamView(View):
def get(self,request):
name = request.GET.get('name','小明')
age = request.GET.get('age','0')
return http.HttpResponse("查询参数:name:%s age:%s" % (name,age))
2:注册子路由和总路由。
path("querystring/",views.QSParamView.as_view()),
path("",include("request_response.urls")),
3:出现的问题:
提取查询字符串参数不区分请求方式,即使客户端进行POST方式的请求,依然可以通过request.GET获取请求中的查询字符串参数。
QueryDict是由Django自己封装的一个数据类型,继承自python的字典Dict它被定义在django.http.QueryDict中,它专门用来存储请求中提取的查询字符串参数和请求体参数
即,HttpRequest对象中的属性GET、POST都是QueryDict类型的数据。
4:推荐使用get的方式取值,因为[]的方式一旦找不到,程序就会报错。
# 如果键不存在则返回None值,可以设置默认值进行后续处理
query_dict.get('键',默认值)
# 可简写为:
query_dict['键']
三:提取请求体数据:
3.1:表单类型请求体数据(Form Data)
前端发送的表单类型的请求体数据,可以通过request.POST属性获取,并返回QueryDict对象。
request.POST只能用来获取POST表单发送的请求体数据
# 表单类型请求体数据
class FormDataParamView(View):
def post(self, request):
username = request.POST.get("username")
password = request.POST.get("password")
return http.HttpResponse("表单数据请求提数据是:username:%s password:%s" % (username,password))
path("formdata/", views.FormDataParamView.as_view()),
3.2:非表单类型请求体数据(Non-Form Data):JSON
非表单类型的请求体数据,Django无法自动解析,可以通过request.body属性获取最原始的请求体数据,然后自己按照具体请求体原始数据的格式(JSON等)进行解析。
request.body获取的是bytes类型的请求体原始数据
lass FormDataParamView1(View):
def post(self, request):
json_str = request.body
print(json_str)
json_dict = json.loads(json_str)
username = json_dict.get("username")
password = json_dict.get("password")
return http.HttpResponse("表单数据请求提数据是:username:%s password:%s" % (username,password))
path("json/", views.FormDataParamView1.as_view()),
四:URL路径参数:提取URL路径中的特定部分数据
在定义路由时,可以从URL中获取特定部分的路径参数
Django的路由系统会将提取的路径参数传递到视图的内部
path()和re_path()都可以提取路径参数
4.1:path()提取路径参数:
注意:路由中提取路径参数时,使用的关键字,必须跟视图中参数名一致
测试path()提取普通路径参数:http://127.0.0.1:8000/url_param1/18/提取里面的18
注意:get 方法需要多一个参数。
class URLParam1View(View):
def get(self,request,age):
return http.HttpResponse("路径中的参数是:%s" % age )
path('url_param1/<int:age>/',views.URLParam1View.as_view())
问题:如果存在多个参数呢?
class URLParam1View(View):
def get(self,request,age1,age2):
return http.HttpResponse("路径中的参数是:%s,%s" % (age1,age2) )
path('url_param1/<int:age1>/<int:age2>/',views.URLParam1View.as_view())
访问地址:http://127.0.0.1:8000/url_param1/18/19/
问题2:实现需求1时提取age数字的int: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
}
问题3:http://127.0.0.1:8000/url_param2/18500001111/提取路径中的手机号18500001111,默认的路由转换器中,没有专门用来匹配手机号的路由转换器,所以在使用path()实现需求2时,就无法直接使用默认的路由转换器。
解决方案一:自定义路由转换器
1:定义视图函数
2:在工程根目录下,新建converters.py文件,用于自定义路由转换器
3:在总路由中,注册自定义路由转换器
4:在子路由中使用自定义路由转换器
class URLParam2View(View):
def get(self,request,phone_num):
return http.HttpResponse("路径中的参数是:%s" % phone_num)
class MobileConverter:
# 注意这个regex不能起别的名字
regex = '1[3-9]\d{9}'
# 这里的方法名也不能修改
def to_python(self,value):
# 将匹配到的结果传递到视图内部使用
return int(value)
def to_url(self,value):
# 将匹配到的结果反向解析传值使用
return str(value)
from django.contrib import admin
from django.urls import path, include, register_converter
# 在总路由中注册自定义转换路由
from converters import MobileConverter
register_converter(MobileConverter, 'mobile')
urlpatterns = [
path('admin/', admin.site.urls),
path("",include("users.urls")),
path("",include("request_response.urls"))
]
path('url_param2/<mobile:phone_num>/', views.URLParam2View.as_view()),
分析路由解析流程:当发送http://127.0.0.1:8000/url_param2/18500001111/时需要和总路由进行匹配,总路由注册了自定义的转换器,并且给子路由起别名register_converter(MobileConverter, 'mobile'),当url进入子路由的时候,转换器和地址进行匹配path('url_param2/<mobile:phone_num>/', views.URLParam2View.as_view()),当匹配成功转换器的to_python方法将结果传入视图中的URLParam2View。
解决方案二:re_path()提取路径参数(复杂路径推荐使用)
class URLParam3View(View):
def get(self,request,phone_num):
return http.HttpResponse("路径中的参数是:%s" % phone_num)
re_path(r'^url_param3/(?P<phone_num>1[3-9]\d{9})/$', views.URLParam3View.as_view()),
五:请求头:
以通过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')
print(ret)
return http.HttpResponse('OK')
path("head/",views.HeadersParamView.as_view()),
浙公网安备 33010602011771号