一 请求

一 限制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")

最新文章

  1. 【环境配置】Linux环境下下载、配置java环境、安装eclipse、建立eclipse快捷方式详解
  2. Action&lt;T1, T2&gt;委托
  3. ansible条件使用--实践
  4. Java基础知识强化之IO流笔记79:NIO之 SocketChannel
  5. 【html】【16】高级篇--毛玻璃效果[模糊]
  6. 在一个数组中是否存在两个数A、B的和为M
  7. 单击Android设备后退键,主屏幕键以及旋转屏幕如何影响Activity的生命周期
  8. iOS UIView常用的一些方法setNeedsDisplay和setNeedsLayout 区别
  9. 事件机制-Spring 源码系列(4)
  10. DOM事件代码小结
  11. Longest Palindromic Substring - 字符串中最长的回文字段
  12. 利用rsync+inotify实现数据实时同步脚本文件
  13. openstack的最简单安装
  14. 19.C++-(=)赋值操作符、智能指针编写(详解)
  15. MongoDb进阶实践之七 MongoDB的索引入门
  16. codeforces431C
  17. SSE图像算法优化系列九:灵活运用SIMD指令16倍提升Sobel边缘检测的速度(4000*3000的24位图像时间由480ms降低到30ms)。
  18. 51Nod 1085 背包问题 (01背包)
  19. 【Noip模拟 20160929】选数
  20. php 目录

热门文章

  1. JQuery 页面滚动至指定元素位置
  2. Mac怎么安装Andriod模拟器
  3. java生成uniappKey
  4. GPS时钟装置,北斗卫星授时,ntp校时服务器,网络时间服务器
  5. 计蒜客(Stone Game)01背包
  6. HCIA-ICT实战基础07-访问控制列表ACL进阶
  7. 物联网5G工业网关的特点和应用场景
  8. log调试法
  9. mysql安装及可视化界面
  10. CSS尺寸设置的单位:px、rem、em、vw、vh