一 请求

一 限制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种不同的响应方式:

  1. 响应内容,就是直接返回数据给客户端

    1. 响应html内容【一般用于web前后端不分离的项目】

    2. 响应json内容【一般用于开发web前后端分离的项目的api接口开发】

  2. 响应页面跳转,就是通过返回页面跳转的信息给浏览器,让浏览器自己进行页面跳转

一 响应内容

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

Django视图中的请求与响应的更多相关文章

  1. python的Web框架,Django框架中的请求与响应

    请求与响应 简单流程图 我们先来了解一个请求与响应的大概流程  视图函数接受到的request到底是个什么对象呢? 服务器接收到http协议的请求后,会根据报文创建HttpRequest对象视图函数的 ...

  2. Django 学习第九天——请求与响应

    一.HttpRequest 对象: 服务器接收到http协议的请求后,会根据报文创建 HttpRequest 对象视图函数的第一个参数是HttpRequest 对象再django.http 模块中定义 ...

  3. drf中的请求与响应

    请求与响应(3星) 请求:Request REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST framework提供的扩展了Ht ...

  4. 如何在django视图中使用asyncio(协程)和ThreadPoolExecutor(多线程)

    Django视图函数执行,不在主线程中,直接 loop = asyncio.new_event_loop() # 更不能loop = asyncio.get_event_loop() 会触发 Runt ...

  5. Django视图中使用本地缓存

    Django服务器视图使用缓存可以大大减小服务器的压力,对数据实时性要求不高的场景使用缓存非常适合. 使用Django本地缓存 1. 在settings.py配置CACHES CACHES = { ' ...

  6. Django学习笔记之视图高级-HTTP请求与响应

    Django限制请求method 常用的请求method GET请求 GET请求一般用来向服务器索取数据,但不会向服务器提交数据,不会对服务器的状态进行更改.比如向服务器获取某篇文章的详情. POST ...

  7. drf入门规范、序列化器组件、视图组件、请求与响应

    DRF框架之入门规范 ​ 本篇文章会详细介绍web开发模式.API接口及其接口测试工具.restful规范.还有经常分不清又很重要的序列化与反序列化的部分,初级交接触APIView.Request类. ...

  8. django 视图中执行原生的 sql 查询语句

    可以使用objects的raw()方法执行原生的sql语句,进行对数据库的查询操作,raw()方法只能执行查询语句 query_set = your_model.objects.raw("s ...

  9. Django编写RESTful API(二):请求和响应

    欢迎访问我的个人网站:www.comingnext.cn 前言 在上一篇文章,已经实现了访问指定URL就返回了指定的数据,这也体现了RESTful API的一个理念,每一个URL代表着一个资源.当然我 ...

  10. [diango]理解django视图工作原理

    前言:正确理解django视图view,模型model,模板的概念及其之间的关联关系,才能快速学习并上手使用django制作网页 本文主要讲解自己在学习django后对视图view的理解 在进入正文之 ...

随机推荐

  1. ue4 启动顺序

    GameMode PlayerController Actor Level https://www.cnblogs.com/fjz13/p/6133795.html

  2. Java基础之变量与常量

    变量 定义:可以变化的量. Java是一种强类型语言,每个变量都必须声明其类型. Java变量是程序种最基本的存储单元,其要素包括变量名,变量类型和作用域. //数据类型 变量名 = 值:可以使用逗号 ...

  3. HDFS文件块

    知识点补充 HDFS优缺点: 优点 (1)高容错性.节点存放的副本比较多. (2)适合处理大数据. GB.TB.PB级别的数据都可以处理. (3)可以构建在廉价的机器上,通过多副本机制来提高可靠性. ...

  4. lua中定义变量用and和or连接

    原文链接 最近在写代码中看到lua定义变量有local a = value1 and value2的操作,有些疑问,在此记录一下:当连接两个操作数时,1.对于运算符and,假设它的第一个操作数为假,就 ...

  5. 查看linux进程启动运行时间

    ps -eo pid,tty,user,lstart,etime,cmd|grep nginx 参数说明: pid:进程ID tty:终端 user:用户 lstart:开始时间 etime:运行时间 ...

  6. 端口被占用 for mac

    启用项目提示端口被占用 解决方案: lsof -i : 3010 杀死占用的进程 kill -9 4804 重新启动

  7. 请求接口类型blob,下载文件

    axiosGet () { var This = this var url = '/group1/M00/00/21/MejEvGOX_zOAL2kiAAAAUhB5Iqg138.txt?token= ...

  8. web端测试的测试点和注意事项【转载】

    文章来源:作者:simplesally 出处:https://www.cnblogs.com/simple1025/   [转载] 工作中接触了不同类型的web端系统,内容不同,需求不同,测试关注点也 ...

  9. mysql循环插入分隔符分开的字符串

    CREATE DEFINER=`root`@`localhost` PROCEDURE `test`()BEGIN DECLARE i,help_topic_id INT; SET i=10469; ...

  10. Treewidget 节点的遍历

    父节点的遍历 // Treewidget遍历操作 // 只遍历父节点 int nParentNodeCount = ui->treeWidget->topLevelItemCount(); ...