
浏览者通过在浏览器的地址栏输入网址请求网站
对于Django开发的网站,有哪一个视图进行处理请求,是由url匹配找到的,配置流程如下:
指定url配置:ROOT_URLCONF= ‘项目.urls’

匹配成功后,包含到应用的urls.py:path(‘’,include(‘应用.urls’))

path(‘’,views.函数名)


from django.urls import path
from book.views import index
urlpatterns = [
# name就是url的名字,可以通过name找到这个路由
path('index/', index, name='home'),
]

from django.http import HttpResponse
from django.shortcuts import render, redirect, reverse
from book.models import BookInfo, PeopleInfo
# Create your views here.
def index(request):
"""
登录成功、注册成功等都需要跳转到首页
1、不使用路由名字时的跳转页面
return redirect('/index/')
2、使用路由名字时的跳转页面,路由是动态获取
path = reverse('index')
return redirect(path)
"""

from django.contrib import admin
from django.urls import path, include
from book.views import index
urlpatterns = [
path('admin/', admin.site.urls),
# 在include中添加第二参数 namespace,这样原来路由的name就变成了 namespace:name, 如 book:home
# namespace习惯上使用子应用的名字,容易识别还不会重名
path('', include('book.urls', namespace='book')),
]

from django.urls import path
from book.views import index
app_name = 'book'
urlpatterns = [
# name就是url的名字,可以通过name找到这个路由
path('index/', index, name='home'),
]

from django.shortcuts import render, redirect, reverse
from book.models import BookInfo, PeopleInfo
# Create your views here.
def index(request):
"""
登录成功、注册成功等都需要跳转到首页
1、不使用路由名字时的跳转页面
return redirect('/index/')
2、使用路由名字时的跳转页面,路由是动态获取
path = reverse('home')
return redirect(path)
3、如果设置了namespace就需要通过namespace:name来获取路由
path = reverse('book:home')
return redirect(path)
"""
PostMan是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件,可以直接去对我们写出来的路由和视图函数进行调试,是后端程序员必须会用的一个工具。

安装

注册免费账号,


保存账号密码,省得每次都得输入



利用HTTP协议向服务器传参有四种途径:






正则分组匹配所有整数数字 (\d+)

from django.urls import path
from book.views import index, detail
from django.conf.urls import url
app_name = 'book'
urlpatterns = [
# name就是url的名字,可以通过name找到这个路由
path('index/', index, name='home'),
# http://127.0.0.1:8000/category_id/book_id
# 根据位置来获取url中传递的参数
url(r'^(\d+)/(\d+)/$', detail),
]
利用正则别名(?P\d+)传递关键字,推荐使用,不用考虑位置问题,只要关键字对应就行。


实际项目路由都是关键字参数


from django.urls import path
from book.views import index, detail1, detail2
from django.conf.urls import url
app_name = 'book'
urlpatterns = [
# name就是url的名字,可以通过name找到这个路由
path('index/', index, name='home'),
# http://127.0.0.1:8000/category_id/book_id
# 根据位置来获取url中传递的参数
url(r'^(\d+)/(\d+)/$', detail1),
# 关键字传递参数,推荐使用
url(r'^(?P\d+)/(?P\d+)/$' , detail2),
]
# 关键字传递参数,函数接收关键字
def detail2(request, categeory_id, book_id):
print(categeory_id, book_id)
return HttpResponse('detail')
获取请求路径中的查询字符串参数(形如?1=v1&k2=v2),可以通过 requestget属性获取,返回QueryDict对象。
注意:查询字符串不区分请求方式,即假使客户端进行POST方式的请求,依然可以通过 request GET获取请求中的查询字符串数据。
PostMan模拟 

HttpRequest对象的属性GET、POST都是QueryDict类型的对象
与python字典不同, QueryDict类型的对象用来处理同一个键带有多个值的情况


# 查询字符串
def detail3(request, categeory_id, book_id):
"""
查询字符串,以百度查询python为例
https://www.baidu.com/s?wd=python&rsv_spt=1&rsv_iqid=0x8662fdc7003bb4a1&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=49055317_10_hao_pg&rsv_enter=1&rsv_dl=ib&rsv_sug3=17&rsv_sug1=16&rsv_sug7=100
上面的url以问号作为分隔,前面是路由,https://www.baidu.com/s
问号后面是get传递的参数,称之为查询字符串,它的形式是,?key=value&key=value&key=value...
成熟系统中,用户在登录输入用户名和密码的时候,理论上,用户名和密码都应该以POST方式进行传递
现在,为了便于学习,采用get方式传递用户名和密码
get传递的用户名和密码在 request.GET 中
"""
# 前端:http://127.0.0.1:8000/2/200?user_name=zhangsan&password=123
# query_params = request.GET
# print(query_params) #
# print(type(query_params)) #
# # 后台获取用户名密码
# user_name = query_params['user_name']
# print(user_name) # zhangsan
# password = query_params.get('password')
# print(password) # 123
"""
QueryDict 与普通python字典的区别
1、QueryDict可以获取url中的一键多值,以 key:[value1, ..., value2] 的形式存储
2、QueryDict获取的一键多值,以普通字典key的方式提取,只能提取到最后的一个值(value2),不能提取到值列表[value1, ..., value2]
3、想获取QueryDict的一键多值,需要用QueryDict的getlist方法,形如:QueryDict.getlist('user_name')
"""
# 前端:http://127.0.0.1:8000/2/200?user_name=zhangsan&password=123&user_name=lisi
query_params = request.GET
print(query_params) #
print(type(query_params)) #
# 后台获取用户名密码
user_name = query_params['user_name'] # 字典key方法,只能获取一键多值的最后一个
print(user_name) # lisi
users = query_params.getlist('user_name') # QueryDict.getlist方法,可以获取一键多值的值列表
print(users) # ['zhangsan', 'lisi']
password = query_params.get('password') # QueryDict.get方法,同字典key方法
print(password) # 123
return HttpResponse('detail-3')
请求体数据格式不固定,可以是表单类型字符串,可以是JSON字符串,可以是ML字符串应区别对待,
可以发送请求体数据的请求方式有 POST、PUT、PATCH、DELETE。
Django默认开后了CSRF防护,会对上述请求方式进行CSRF防护验证,在测试时可以关闭CSRF防护机制,方法为在 settings py文件中注释掉CSRF中间件。
注意:①网址url以斜线结束。②注释掉settings中的CRSF安全设置






# POST表单数据,
def detail4(request, categeory_id, book_id):
print(categeory_id, book_id)
"""
1、使用request.POST方法获取前端传输的数据
2、request.POST方法获取的结果为QueryDict,与request.GET获取的结果是样的
3、一键一值和一键多值的数据处理方式与GET方法完全相同
"""
data = request.POST
print(data) #
user_name = data['user_name']
print(user_name) # lisi
user_name = data.get('user_name')
print(user_name) # lisi
users = data.getlist('user_name')
print(users) # ['zhangsan', 'lisi']
password = data.get('password')
print(password) # 123
return HttpResponse('detail-4')
非表单类型的请求体数据, Django无法自动解析,可以通过 request.body属性获取最原始的请求体数据,自己按照请求体格式(JSON/XML等)进行解析 request.body返 bytes回类型,然后通过decode()解码为JSON形式的字符串数据,再通过json.loads()转换为字典数据,就可使用了。


# POST JSON数据,
def detail5(request, categeory_id, book_id):
import json
print(categeory_id, book_id)
"""
1、json数据的样式,注意:①只能用双引号,不能用单引号。②最好一行数据后面不能加逗号
{
"user_name": "zhangsan",
"password": "123"
}
2、通过Ajax发送的JSON数据并没有记录在 request.POST 中,而是记录在 request.body 中
3、request.body获取到的是bytes类型数据,可以通过decode()转换为JSON形式的str类型,再通过json.loads转换为字典
4、json模块:
json.dumps,将字典转换为JSON形式的字符串
json.loads,将JSON形式的字符串转换为字典
"""
data = request.POST
print(data) #
body = request.body
print(body) # b'{\r\n "user_name":"zhangsan",\r\n "password":"123"\r\n}'
print(type(body)) #
body_str = body.decode() # 对bytes数据解码,结果为str
print(body_str) # {
# "user_name": "zhangsan",
# "password": "123"
# }
print(type(body_str)) #
body_dict = json.loads(body_str) # 将JSON形式的字符串转换为字典
print(body_dict) # {'user_name': 'zhangsan', 'password': '123'}
print(type(body_dict)) #
return HttpResponse('detail-5')
可以通过 request.META属性获取请求头headers中的数据,request.META为字典类型。
常见的请求头如:


# http报文头(header) request.META
def detail6(request, categeory_id, book_id):
# print(request.META)
content_type = request.META['CONTENT_TYPE']
print(content_type) # text/plain
name = request.META['HTTP_NAME']
print(name) # ruhua
return HttpResponse('detail-6')




# 其他常见HttpRequest对象属性
def detail7(request, categeory_id, book_id):
print(request.method)
return HttpResponse('detail-7')