一 请求
一 限制http请求
视图中的request,实际上是django源码中的HTTPRequest的子类WSGIRequest类的实例对象,主要由django对客户端请求的http协议报文进行解析后得到的请求相关数据都在request对象中。web项目运行在http协议下,默认肯定也支持用户通过不同的http请求方法发送数据到服务端。常用的http请求方法:
HTTP请求方法 | 描述 |
---|---|
POST | 添加/上传 |
GET | 获取/下载 |
PUT | 修改/更新,修改整体 |
PATCH | 修改/更新,修改部分 |
DELETE | 删除/废弃 |
Django支持让客户端只能通过指定的Http请求来访问到项目的视图。views.py 代码:
# 让用户发送POST才能访问的页面 from django.views.decorators.http import require_http_methods @require_http_methods(["POST"]) # 注意,中括号中的请求方法名务必大写!!!否则无法正常显示 def login(request): return HttpResponse("登录成功!")
二 视图接收http请求
在http请求和响应过程中, 用户往往会在请求过程中发送请求信息给服务端。那么客户端发送请求数据一般无非以下几种格式:
1 获取查询字符串的参数(request.GET)
查询字符串就是url地址上面?号后面的数据,例如:http://127.0.0.1:8000/index?name=xiaoming&pwd=123456。
上面name=xiaoming&pwd=123456就是查询字符串,可以通过request.GET来获取。
注意: GET不是http请求,也就是说,只要地址上有查询字符串,不管使用什么样的http请求方法,都可以使用获取request.GET来获取
from django.http.response import HttpResponse from django.views.decorators.http import require_http_methods from django.http import QueryDict def index(request): print("index视图运行了") # print(request.method) # print(request.headers) # print(request.body) # print(request.path) """获取查询字符串""" """ 请求地址:http://127.0.0.1:8000/home/index """ print(request.GET) # 获取地址栏上的所有的查询字符串,组成一个QueryDict查询字典对象 """ 打印效果:<QueryDict: {}> QueryDict的声明位置: from django.http import QueryDict QueryDict的父类继承的就是dict字典,所以字典提供的方法或者操作, QueryDict都有 之所以使用QueryDict来保存请求参数的原因时:默认的字典的键是唯一的,所以会导致如果有多个值使用了同一个键,则字典会覆盖的。 而django内部封装的QueryDict允许多个值使用了同一个键,会自动收集所有的值保存在一个列表中作为当前键的值区寄存起来。 QueryDict常用的方法有2个: get(键) 通过指定键获取最后1个值 getlist(键) 通过指定键获取所有值,并以列表格式返回 """ """ 请求地址:http://127.0.0.1:8000/home/index?name=xiapming&mobile=13312345678 """ print(request.GET.get("mobile")) print(request.GET.get("name")) print(request.GET.get("pwd", 123)) # print(request.Get["pwd"]) # 减少使用中括号,会在没有键的情况下导致程序报错 """ 打印效果: 13312345678 xiapming 123 """ """ 请求地址:http://127.0.0.1:8000/home/index?name=xiaoming&mobile=13312345678&lve=swimming&lve=shopping&lve=game """ print(request.GET.get("lve")) # game print(request.GET.getlist("lve")) # ['swimming', 'shopping', 'game'] print(request.GET.getlist("name")) # ['xiaoming'] return HttpResponse("<h1>index</h1>") @require_http_methods(["POST"]) # 注意,中括号中的请求方法名务必大写!!!否则无法正常显示 def login(request): return HttpResponse("登录成功!")
2 获取请求体数据(request.POST)
在各种http请求方法中,POST/PUT/PATCH都是可以设置请求体的。request.POST中获取客户端通过POST发送过来的请求体,无法获取PUT/PATCH的请求体。
# @require_http_methods(["POST", "PUT"]) # 注意,中括号中的请求方法名务必大写!!!否则无法正常显示 def index2(request): """获取请求体数据""" """ 访问地址:http://127.0.0.1:8000/home/index2 请求体:不设置请求体 """ # print(request.POST) """ request.POST获取的结果也是QueryDict查询字典对象 <QueryDict: {}> """ """ 访问地址:http://127.0.0.1:8000/home/index2 请求体:name=xiaoming&age=16 """ # print(request.POST) """ 打印效果: <QueryDict: {'name': ['xiaoming'], 'age': ['16']}> """ # print(request.POST.get("name")) """ 访问地址:http://127.0.0.1:8000/home/index2 请求体:name=xiaoming&age=16&citys=["北京", "上海", "天津] """ """ 打印效果: <QueryDict: {'name': ['xiaoming'], 'age': ['16'], 'citys': ['北京', '上海', '天津']}> """ # print(request.POST) # ['北京', '上海', '天津'] # print(request.POST.getlist("citys")) # print(request.POST.get("citys")) # 天津 """接收原生请求体中的json数据""" """ 请求地址:http://127.0.0.1:8000/home/index2 请求体为json:'{"name": "xiaobai","age": 16}' """ # print(request.POST) # <QueryDict: {}> # print(request.body) # b'{\n "name": "xiaobai",\n "age": 16\n}' # import json # print(json.loads(request.body)) # {'name': 'xiaobai', 'age': 16} return HttpResponse("index2!")
3 获取请求头数据(request.headers)
def index3(request): """接收请求体参数""" print(request.META) # 获取当前项目相关的服务器与客户端环境信息,也包含了请求头信息,以及服务端所在的系统的环境变量 """ { 'LANG': 'zh_CN.UTF-8', # 服务端系统的默认语言 'USER': 'moluo', # 服务端运行的系统用户名 'HOME': '/home/moluo', # 服务端运行的系统用户家目录路径 'DJANGO_SETTINGS_MODULE': 'djdemo.settings', # 只有在django下才有的,当前django框架运行时加载的配置文件导包路径 'SERVER_NAME': 'ubuntu', # 服务端系统名称 'SERVER_PORT': '8000', # 服务端的运行端口 'REMOTE_HOST': '', # 客户端的所在IP地址,有时候可能是域名 'SCRIPT_NAME': '', # 客户端本次请求时,服务端执行的程序所在路径 'SERVER_PROTOCOL': 'HTTP/1.1', # 服务端运行的协议 'SERVER_SOFTWARE': 'WSGIServer/0.2', # 服务端运行web服务器的软件打印信息 'REQUEST_METHOD': 'POST', # 客户端本次请求时的http请求方法 'PATH_INFO': '/home/index3/', # 客户端本次请求时的url路径 'QUERY_STRING': '', # 客户端本次请求时的查询字符串 'REMOTE_ADDR': '127.0.0.1', # 客户端的所在IP地址 'CONTENT_TYPE': 'application/json', # 客户端本次请求时的数据MIME格式 'HTTP_USER_AGENT': 'PostmanRuntime/7.26.10', # 客户端本次请求时,所使用的网络代理软件提示信息 'HTTP_ACCEPT': '*/*', # 客户端期望服务端返回的数据MIME格式格式 'HTTP_HOST': '127.0.0.1:8000', # 客户端本次请求时,所使用服务端地址 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br', # 客户端期望服务端返回的数据的压缩格式 'HTTP_CONNECTION': 'keep-alive', # 客户端支持的服务端协议的链接类型,keep-alive 表示客户端支持http的长连接 } """ print(request.headers) # 获取HTTP请求头 """ { 'Content-Length': '601', // 客户端本次请求的内容大小 'Content-Type': 'multipart/form-data;', # 客户端本次请求的内容MIME类型 'User-Agent': 'PostmanRuntime/7.26.10', # 客户端本次请求的代理软件打印信息 'Accept': '*/*', 'Host': '127.0.0.1:8000', # 客户端本次请求的服务端地址 'Accept-Encoding': 'gzip, deflate, br', 'Connection': 'keep-alive', # 以下就是自定义请求头了 'Company': 'baidu', 'Num': '1000', } """ print("Content-Type=", request.META.get("CONTENT_TYPE")) print("自定义请求头,Num=", request.META.get("HTTP_NUM")) print("自定义请求头,Company=", request.META.get("HTTP_COMPANY"))
print("Content-Type=", request.headers.get("Content-Type")) print("自定义请求头,Num=", request.headers.get("Num")) print("自定义请求头,Company=", request.headers.get("Company")) return HttpResponse("接收请求体")
4 获取上传文件(request.FILES)
def index4(request): """接收上传文件""" # print(request.FILES) """ POST http://127.0.0.1:8000/home/index4 打印效果: <MultiValueDict: {'avatar': [<InMemoryUploadedFile: 1.jpg (image/jpeg)>]}> """ # print(request.FILES.get("avatar")) # 获取本次客户端上传的指定name值对应的一个文件上传处理对象 # print(request.FILES.getlist("avatar")) # 获取本次客户端上传的指定name值对应的多个文件上传处理对象 """ django在解析http协议的时候,针对上传文件,会自动实例化一个内存保存文件的文件上传处理对象InMemoryUploadedFile from django.core.files.uploadedfile import InMemoryUploadedFile """ # read() 从文件上传处理对象读取文件的内容(bytes格式内容) import os # # 处理一个上传文件[不仅是图片,任何内容都可以这样处理] # file = request.FILES.get('avatar') # with open(f"{os.path.dirname(__file__)}/{file.name}", "wb") as f: # f.write(file.read()) # 处理多个一次性上传文件 for file in request.FILES.getlist("avatar"): with open(f"{os.path.dirname(__file__)}/{file.name}", "wb") as f: f.write(file.read()) return HttpResponse("接收客户端的上传文件")
二 响应
django和大多数的web框架一样,针对http的响应,提供了2种不同的响应方式:
-
响应内容,就是直接返回数据给客户端
-
响应html内容【一般用于web前后端不分离的项目】
-
响应json内容【一般用于开发web前后端分离的项目的api接口开发】
-
-
响应页面跳转,就是通过返回页面跳转的信息给浏览器,让浏览器自己进行页面跳转
一 响应内容
1 返回HTML数据
def index5(request): """响应对象""" """ return HttpResponse(content="正文内容",content_type="内容格式",status="http响应状态码") content 响应内容 content_type 内容格式,默认是 text/html status 响应状态码,默认是 200 headers 响应头,字典格式 """ """返回html内容""" return HttpResponse("<h1>你好,django</h1>")
2 返回Json数据
def index6(request): """响应对象:响应json数据""" # 返回字典数据作为json给客户端 """ import json data = {"name":"xiaoming", "age":16, "sex": True} return HttpResponse(json.dumps(data), content_type="application/json;charset=utf-8") """ # 原生返回json数据,太麻烦了 # 因此django提供了一个HttpResponse的子类JsonResponse,转换提供给我们返回json数据的 # from django.http.response import JsonResponse # data = {"name": "xiaoming", "age": 16, "sex": True} # return JsonResponse(data) # JsonResponse返回的数据如果不是字典,则必须要加上safe参数声明,并且值为False # 返回列表数据给客户端 from django.http.response import JsonResponse data = [ {"id":1, "name": "小明", "age": 16}, {"id":3, "name": "小火", "age": 15}, ] return JsonResponse(data, safe=False) # return JsonResponse(data, safe=False, json_dumps_params={"ensure_ascii": False}) # 不推荐使用
3 返回图片格式信息
例如:图片,压缩包,视频,或js脚本
def index7(request): """返回图片格式""" import os with open(f"{os.path.dirname(__file__)}/avatar.jpg", "rb") as f: content = f.read() return HttpResponse(content, content_type="image/jpeg")
4 提供下载压缩包
def index8(request): """返回压缩包格式""" import os with open(f"{os.path.dirname(__file__)}/code.zip", "rb") as f: content = f.read() return HttpResponse(content, content_type="application/zip")
5 自定义响应头
def index9(request): """返回数据的过程中设置响应头""" response = HttpResponse("ok") # 自定义响应头[值和属性都不能是多字节] response["company"] = "baidu" return response
二 响应页面跳转
页面跳转也有2种方式:站外跳转与站内跳转。
1 站外跳转
def index10(request): """跳转到站外""" # 1. 基于django提供的Response对象也可以进行页面跳转 # from django.http.response import HttpResponse # response = HttpResponse(status=301) # response["Location"] = "https://www.tmall.com" # return response # # 2. 基于django提供的Response对象的原生写法[HttpResponseRedirect与HttpResponsePermanentRedirect都是HttpResponse的子类] # from django.http.response import HttpResponseRedirect # 临时重定向 # # from django.http.response import HttpResponsePermanentRedirect # 永久重定向 # return HttpResponseRedirect("https://www.qq.com") # 2. 基于django提供快捷函数(简写函数, shortcuts)来完成[常用] from django.shortcuts import redirect return redirect("http://www.baidu.com")
2 站内跳转
在站内跳转时,如果使用django.urls.reverse函数进行路由反转解析(可以根据路由的别名反向生成路由的URL地址),则必须在总路由文件和子路由文件中,对路由的前缀和子路由后缀进行别名绑定,步骤如下:djdemo/urls.py,总路由,代码:
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('home/', include('home.urls', namespace="index")), # namespace 是include函数的参数,namespace的值就是提供给reverse使用的 ]
home/urls.py
,子路由,代码:
from django.urls import path from home import views # 使用路由反向解析,reverse时必须在当前路由文件中设置app_name为当前子应用的包名 app_name = "home" urlpatterns = [ 。。 path('index11', views.index11, name="in11"), path('index12', views.index12, name="in12"), ]
home/views.py,代码:
def index11(request): """跳转到站内""" from django.shortcuts import redirect # 根据指定的url地址,进行页面跳转 # # 直接基于redirect跳转 # return redirect("/home/index12") # # 基于reverse+redirect对路由别名进行反向解析进行跳转 from django.urls import reverse # 根据路由别名,反向解析生成url地址 url = reverse("index:in12") print(url) return redirect(url) def index12(request): return HttpResponse("ok, index12")
标签:http,请求,request,视图,Django,响应,print,django,客户端 From: https://www.cnblogs.com/daminghuahua/p/16931852.html