一、模板
- 什么是模板?
在MVT模式中,T/Template就是模板,负责封装和生成要返回的html。 - 例子:创建一个模板html,浏览器请求url,则返回该html返回到浏览器
1.在templates
创建index.html
文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Django的第一个应用</title>
</head>
<body>
<h2>首页</h2>
</body>
</html>
2.修改之前polls/views.py
的内容,Index请求类的get方法的返回值改为上面创建好的index.html
class Index(View):
"""
类视图,需继承View类
"""
def get(self, request):
# render(request对象,读取html文件并返回给浏览器)
return render(request, 'index.html')
def post(self, request):
return HttpResponse("hello, django. You're at the polls index.==>POST")
结果:二、Django接收参数request
有些好奇,当发送请求给Django的View后,View接受到的request对象是什么内容,参数又是什么样子的
-
通过debug进行查看
1.在polls/views.py
打断点:
2.点击debug,进入debug模式
3.浏览器访问如下情况链接: -
get请求带参:http://localhost:8000/polls/?one=1&two=2&one=3
request.GET
:返回一个类似字典的内容,其中第一个one=1没有显示,但是实际好像接受了,通过request. GET.getlist(key)
能看到
request.GET.get(key)
:可获取到对应的value,如果有多个相同key,则获取到的是最后一个value。因为字典中key是唯一的,但是实际上貌似全部都接收了。
request. GET.getlist(key)
:可获得所有相同key的value,返回列表。有两个one的键值对:
-
post请求,发送form表单
坑位:发送post请求403,然后响应内容是:
解决方法:
1.到settings.py
注释下面这行(不推荐)
2.解决cookie没有csrf_token的问题
前端form表单所在的html中添加
{{ csrf_token }}
,这样请求时就会携带上csrf_token
给服务端
使用postman发送带form表单的post请求(form-data):
用request.POST
来获取form表单的内容,结果和GET类似:
也可以使用request.POST.get(key)
和request.POST.getlist(key)
,其结果和get的一样
- 使用postman发送带有json格式参数的post请求:
通过request.body
可看到:
decode
一下:
三、render
- 一个
render
函数会返回一个经过字典数据渲染后的模板封装而成的HttpResponse
对象 -
render(request, 模板html、传给模板html的字典数据)
参数:
1.request
:请求对象,就是view函数的第一个参数
2.模板html
:模板所对应的html文件
3.字典数据
:该数据会传递给第二个参数中的html文件 - 例子:
from django.shortcuts import render
from .models import Question
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
context = {'latest_question_list': latest_question_list}
return render(request, 'polls/index.html', context)
四、抛出404错误
如果访问的资源不存在的话,我们想抛出404错误,而不是暴露Django的错误信息。Django为我们提供了这样一个方法
get_object_or_404()
:将一个Django模型作为第一个位置参数,后面可以跟上任意个数的关键字参数,如果对象不存在则弹出Http404错误。为什么我们使用辅助函数
get_object_or_404()
而不是自己捕获ObjectDoesNotExist
异常呢?还有,为什么模型API不直接抛出ObjectDoesNotExist
而是抛出Http404
呢?
因为这样做会增加模型层和视图层的耦合性。而Django的设计思想中,最重要的思想之一就是要保证松散耦合。一些受控的耦合将会被包含在django.shortcuts
模块中。例子:当id不存在时,抛出404
from django.shortcuts import get_object_or_404, render
from .models import Question
# ...
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question': question})
还有一个
get_list_or_404()
方法
和get_object_or_404()
类似,只不过是用来替代filter()
函数,当查询列表为空时弹出404错误。(filter()
是模型API中用来过滤查询结果的函数,它的结果是一个列表集。而get则是查询一个结果的方法,和filter是一个和多个的区别)当然,因为自带的404等页面太丑,一般都是自定义404、500等页面
1.urls.py
:
from django.contrib import admin
from django.urls import path
from app import views
urlpatterns = [
path('admin/', admin.site.urls),
]
# 增加的条目
handler400 = views.bad_request
handler403 = views.permission_denied
handler404 = views.page_not_found
handler500 = views.error
2.在应用/views.py
文件增加对应的处理视图:
def bad_request(request):
return render(request, '400.html')
def permission_denied(request):
return render(request, '403.html')
def page_not_found(request):
return render(request, '404.html')
def error(request):
return render(request, '500.html')
3.在对应位置创建400.html
等页面文件即可
五、url转换器
在项目中,有事件需要前端传递特定类型的参数过来,比如说int
。那么此时就需要用到Django内置的url转换器,它可以把传递过来的参数转换成指定的类型
-
首先看下源码
from django.urls import converters
,进入converters
类,可看到提供了5种可转换类型: -
IntConverter()
:可传递任意整数
1.[0-9]
整形数字
2.+
一个或多个
-
PathConverter()
:可传递任意字符串、符号等
1..
:任意字符
2.+
:一个或多个
-
SlugConverter()
1.'[-a-zA-Z0-9_]+'
:由-
或a-z
或A-Z
或0-9
或_
中的一个或多个组成的字符串
-
StringConverter()
:默认的转换器
1.[^/]+
:除了/
之外的都可以
UUIDConverter()
:
1.[0-9a-f]
:表示只能是0到9之间的任意整形数字和a-f 之间的字母
2.{8}
:表示只能有8个这样的字母或者数字。
3.-
即指定了这个字符,必须使用它,整个字符窜的意思就是8个[0-9a-f]
,后面用一个-
连接
4.后面的以此类推总结
'int': IntConverter()
:一个或多个整数(0-9)
'path': PathConverter()
:所有字符串
'slug': SlugConverter()
:英文中的横杆或者英文字符或者阿拉伯数字或者下划线
'str': StringConverter()
除了斜杠/以外的所有字符
'uuid': UUIDConverter()
:只有满足uuid形式的字符串例子
1.在polls/views.py
添加一个视图方法,用于接收id参数并返回
from django.http import HttpResponse
from django.views import View
class Index(View):
"""
类视图,需继承View类
"""
def get_id(request, id):
return HttpResponse(F'id是{id}')
2.在polls/urls.py
添加对应的映射
urlpatterns = [
path(r'get_id/<int:id>', views.get_id, name='get_id')
]
3.访问http://localhost:8000/polls/get_id/3
如果参数不是整数,传递过去后无法转换成int类型,则会404,比如访问http://localhost:8000/polls/get_id/3.2
五、响应json内容
响应字符串、响应模板都试过了,那么是否可以响应json数据呢?这时候就需要用到JsonResponse
PS.JsonResponse
第一个参数默认必须为dict,如果不想如此,需要设置safe=false
,则为return JsonResponse(value, safe = false)
1.polls/views.py
添加代码:
# Create your views here.
from django.http import JsonResponse
def response_json(request):
# 响应json内容
return JsonResponse(
{
"name": "lzl",
"gender": "man"
}
)
-
polls/urls.py
添加映射
path('json', views.response_json)
3.访问http://localhost:8000/polls/json
4.结果: