文章目录
一.request对象
1.概念
Django框架根据Http请求报文自动生成的一个对象,包含了请求各种信息。
2.属性
创建主路由:
url(r'^req/',include('ReqApp.urls'))
(1)path
path:请求的完整路径
创建子路由:
url(r'^testReq/',views.testReq),
生成视图函数:
def testReq(request):
print(request.path)
return HttpResponse('testReq')
运行结果:
(2)method
GET 1.11版本最大参数的数据量2K,参数会显示在浏览器的地址栏上,不安全
POST 参数存在请求体中,文件上传等,相对安全
请求的方法,常用GET,POST
应用场景:前后端分离的底层、判断请求方式、执行对应的业务逻辑
def testReq(request):
print(request.method)
return HttpResponse('testReq')
(3)GET
视图函数:
def testReq(request):
# 获取get请求方式的参数
name = request.GET.get('name')
age = request.GET.get('age')
print(name,age)
return HttpResponse('testReq')
使用postman工具来访问,运行结果:
思考:request.GET是什么类型???
print(request.GET) ------》 <QueryDict: {‘name’: [‘zs’], ‘age’: [‘18’]}>
倘若又加一个参数,会怎么样?
取所有值:
def testReq(request):
# print(request.path)
print(request.GET)
# name = request.GET.get('name')
# age = request.GET.get('age')
# print(name,age)
name_list = request.GET.getlist('name')
print(name_list)
return HttpResponse('testReq')
运行结果:
总结:
QueryDict 类字典结构:key-value
一个key可以对应多个值
get 获取最后一个
getlist 获取多个
类似字典的参数,包含了get请求方式的所有参数
(4)POST
视图函数:
def testReq(request):
print(request.POST)
return HttpResponse('testReq')
输入post请求路径,并在postman中添加key-value的值
运行结果:
在执行post会遇到403 Forbidden这个问题,解决这个问题的方案有三种,这里讲下最简单的解决方案:
注释settings中的csrf中间件
再次运行,运行结果:
取值:
视图函数:
def testReq(request):
print(request.POST)
print(request.POST.get('name'))
print(request.POST.getlist('name'))
return HttpResponse('testReq')
运行结果:
POST:类似字典的参数,包含了post请求方式的所有参数
拓展:
1.QueryDict和Dict的区别?
dict是字典对象,没有urlencode()方法;
QueryDict对象,有urlencode()方法,作用是将QueryDict对象转换为url字符串;
eg:print(request.GET.urlencode())
一般QueryDict通过params = copy.deepcopy(request.GET)得到的,这时params是QueryDict对象;
也能params[key]=value进行添加数据
2.哪些请求方式会报错403?
get不需要,除了get都需要:post、put、patch、delete
(5)encoding
encoding:编码方式,常用utf-8
应用场景:
当你请求的时候,服务器响应之后有乱码问题,那么是因为你请求的时候没有指定编码格式
一般这种请求在python很少见,除非操作系统区别太大
这样可以在请求的时候设置请求的编码格式
request.encoding = 'utf-8'
这句话是设置请求头的编码格式
(6)META
应用场景:反爬虫,REMOTE_ADDR,拉入黑名单,展示客户端的所有信息及ip
例如获取主机地址:
def testReq(request):
print(request.META.get('REMOTE_ADDR'))
return HttpResponse('testReq')
查看META里都有什么:
def testReq(request):
for m in request.META:
print(m,request.META.get(m))
return HttpResponse('testReq')
运行结果:
二.视图函数的返回值
当浏览器访问服务器的时候,那么服务器响应的数据类型有两种,分别是HTML响应和JsonResponse(前后端分离)
1.HTML响应
(1)HttpResponse
不使用模板,直接HttpResponse()
创建主路由:
url(r'^res/',include('ResApp.urls'))
创建子路由:
url(r'^testResponse/',views.testResponse),
生成视图函数:
def testResponse(request):
response = HttpResponse()
response.content ='英雄联盟'
response.status_code = 404
# 直接写出文本
response.write('亚索')
# 一次性读取剩余字节,冲刷缓存区
response.flush()
return response
运行结果:
(2)render
render方法的返回值类型也是一个HttpResponse
创建子路由:
url(r'^testRender/',views.testRender),
生成视图函数:
def testRender(request):
return render(request,'testRender.html')
对render进行剪切一下,方便查看类型
def testRender(request):
response = render(request,'testRender.html')
print(type(response))
return response
创建testRender.html模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
哈哈哈哈哈哈
</body>
</html>
运行结果:
(3)HttpResponseRedirect
HttpResponseRedirect:重定向
其是HttpResponse的子类,响应重定向:可以实现服务器内部跳转
创建子路由:
url(r'^testRedirect/',views.testRedirect),
生成视图函数:
def testRedirect(request):
# 重定向就是执行其他的视图函数
return HttpResponseRedirect('/res/index/')
上面把路径写死了,为避免这种情况,我们也可以使用反向解析:
修改主路由:
url(r'^res/',include('ResApp.urls',namespace='res'))
修改子路由:
url(r'^index/',views.index,name='index'),
视图函数:
def testRedirect(request):
return HttpResponseRedirect(reverse('res:index'))
运行结果:
查看HttpResponseRedirect类型:
def testRedirect(request):
response = HttpResponseRedirect(reverse('res:index'))
print(type(response))
return response
运行结果:
说明:
方法的返回值类型是HttpResponseRedirect
HttpResponseRedirect继承了HttpResponseRedirectBase
HttpResponseRedirectBase继承了HttpResponse
状态码是302
重定向的简写方式:(常用)
创建子路由:
url(r'^testSimpleRedirect/',views.testSimpleRedirect),
生成视图函数:
def testSimpleRedirect(request):
return redirect(reverse('res:index'))
运行结果:
拓展:
redirect方法是通过一个参数来确定是永久重定向还是普通的重定向
如果是永久重定向,那么类就是HttpResponsePermanentRedirect,状态码是301
如果是普通重定向,那么类就是HttpResponseRedirect,状态码是302
HttpResponsePermanentRedirect和HttpResponseRedirect分别继承HttpResponseRedirectBase
HttpResponseRedirectBase继承了HttpResponse
2.JsonResponse
django的视图函数,是不可以直接返回data的
JsonResponse 缺点:1.中文乱码 2.序列化
创建子路由:
url(r'^testJson/',views.testJson),
生成视图函数:
def testJson(request):
data = {
'msg': 'ok',
'status': 200,
'name': '张三',
}
return JsonResponse(data=data)
运行结果:
我们会发现出现了中文乱码的问题。
解决中文乱码方案:
def testJson(request):
data = {
'msg': 'ok',
'status': 200,
'name': '张三',
}
# 忽略编码
return JsonResponse(data=data,json_dumps_params={'ensure_ascii':False})
运行结果:
序列化问题:
创建模型:
class Animal2(models.Model):
name = models.CharField(max_length=32)
class Meta:
db_table = 'animal2'
添加数据:
视图函数:
def testJson(request):
animal = Animal2.objects.first()
data = {
'msg': 'ok',
'status': 200,
'name': '张三',
'animal':animal
}
return JsonResponse(data=data,json_dumps_params={'ensure_ascii':False})
运行结果:
django默认的视图函数,是不支持序列化的。
解决序列化方案:
在模型中定义一个方法:
class Animal2(models.Model):
name = models.CharField(max_length=32)
class Meta:
db_table = 'animal2'
# 当对象调用了to_dict方法之后,那么会返回一个字典
def to_dict(self):
return {'name':self.name}
在视图函数中调用这个方法:
def testJson(request):
animal = Animal2.objects.first()
data = {
'msg': 'ok',
'status': 200,
'name': '张三',
'animal':animal.to_dict()
}
return JsonResponse(data=data,json_dumps_params={'ensure_ascii':False})
运行结果:
若是想获取全部对象,可如下:
def testJson(request):
# django默认的视图函数,是不支持序列化的,所以我们需要在后面使用django-rest-framework
animal_list = Animal2.objects.all()
a_list=[]
for animal in animal_list:
a_list.append(animal.to_dict())
data = {
'msg': 'ok',
'status': 200,
'name': '张三',
'animal_list':a_list
}
return JsonResponse(data=data,json_dumps_params={'ensure_ascii':False})
运行结果:
JsonResponse这个类是HttpRespon的子类,它主要和父类的区别在于:
1.它的默认Content-Type 被设置为: application/json
2.第一个参数,data应该是一个字典类型,当 safe 这个参数被设置为:False ,那data可以填入任何能被转换为JSON格式的对象,比如list, tuple, set。 默认的safe 参数是 True. 如果你传入的data数据类型不是字典类型,那么它就会抛出 TypeError的异常。
三.反向解析(视图函数)
上一篇博文中的反向解析主要围绕页面,此次主要围绕视图函数,因为一般python代码的反向解析都会结合重定向一起使用。
1.基本使用
形式:reverse(‘namespace:name’)
在上面,我们已经进行了反向解析的基本使用个,这里就不再说明了
2.位置参数
创建子路由:
url(r'^testLocation/',views.testLocation),
url(r'^testReverseLocation/(\d{4})/(\d+)/(\d+)/',views.testReverseLocation,name='testReverseLocation'),
生成视图函数:
def testLocation(request):
return redirect(reverse('res:testReverseLocation',args=[2020,7,29]))
def testReverseLocation(request,year,month,day):
return HttpResponse(year+'/'+month+'/'+day)
运行结果:
运行前:
运行后:
3.关键字参数
创建子路由:
url(r'^testKey/',views.testKey),
url(r'^testReverseKey/(?P<year>\d{4})/(?P<month>\d+)/(?P<day>\d+)/',views.testReverseKey,name='testReverseKey')
生成视图函数:
def testKey(request):
return redirect(reverse('res:testReverseKey',kwargs={'year':2020,'month':7,'day':29}))
def testReverseKey(request,month,day,year):
return HttpResponse(year + '-' + month + '-' + day)
运行结果:
运行前:
运行后:
四.HttpResponse子类
HttpResponse子类
HttpResponseRedirect
-302 重定向,短暂性
HttpResponsePermanentRedirect
-301 重定向,永久性
HttpResponseBadRequest
-400 请求错误
HttpResponseNotFound
- 404 路径错误
HttpResponseForbidden
- 403 csrf 防跨站攻击
HttpResponseNotAllowed
- 405 请求方式不允许
HttpResponseServerError
- 500 服务器错误
Http404- Exception
- raise 主动抛异常出来