今日内容回顾(django 视图层 )
今日内容回顾
网页伪静态
将动态伪装成静态网页,从而提升网页被搜索引擎收录的概率
表现形式就是网址看着像一个具体的文件路径
直接添加后缀即可
path("index.html",view.index)
视图层
视图函数的返回值问题
在视图函数中,其返回值必须返回的是一个HttpResponse对象
def func(request):
pass
# 报错!!!
The view app01.views.func didn't return an HttpResponse object. It returned None instead.
# HttpResponse是一个类,在使用视图函数中它必须要返回一个HttpResponse对象
class HttpResponse(HttpResponseBase):
"""
An HTTP response class with a string as content.
This content that can be read, appended to, or replaced.
"""
streaming = False
# 关于三板斧
def func(request):
# 1.return HttpResponse("返回值")
# 2.return render(request,"路由","xxx")
# 3.redirect("路由")
"""
在视图函数的使用中,HttpResponse,redirect,render
它们都是HttpResponse本身或者间接调用或继承了HttpResponse,
所以它们符合上述,视图函数中它必须要返回一个HttpResponse对象
"""
# 源码中的,render、redirect。
def render():
return HttpResponse(...)
def redirect(to, *args, permanent=False, **kwargs):
redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
return redirect_class(resolve_url(to, *args, **kwargs))
视图函数返回json格式数据
需求让视图函数返回一个json格式数据
def func(request)
user_dict = {'name': 'jason老师', 'pwd': 123,
'hobby': ['read', 'run', 'music']}
# 方式1,使用json模块先序列化在返回
json_str = json.dumps(user_dict, ensure_ascii=False)
return HttpResponse(json_str)
# 方式2,直接使用JsonResponse,相对于方式1更加便捷。
return JsonResponse(user_dict)
"""
JsonResponse默认只序列化字典类型的数据
如果序列非字典类型的数据还需要指定safe参数为False
"""
from django.http import JsonResponse
class JsonResponse(HttpResponse):
def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
json_dumps_params=None, **kwargs):
if json_dumps_params is None:
json_dumps_params = {}
data = json.dumps(data, cls=encoder, **json_dumps_params)
JsonResponse(user_dict, json_dumps_params={'ensure_ascii':False})
form表单携带文件数据
"""
form表单需要具备的条件
1. menthod属性值必须是 post
2.entype属性值必须是 multipart/form-data
"""
# 格式如下:
<form action="" method="post" enctype="multipart/form-data"></form>
# 后端获取文件
def func(request):
print(request.FILES) # 需要用点FILES的方式才能够获取到文件数据
return render(request,'xxx.html')
<MultiValueDict: {'file': [<InMemoryUploadedFile: image-20220614222152619.png (image/png)>]}>
FBV与CBV
基于函数的视图
FBV(function base views) 就是在视图里使用函数处理请求
# urls.py下
path('index/', views.index)
# views.py下
def index(request):
return HttpResponse()
基于类的视图
CBV(class base views) 就是在视图里使用类处理请求。
# urls.py下
path('func/', views.MyView.as_view())
# views.py下
from django import views
class MyView(views.View):
def get(self, request):
return HttpResponse('我是CBV里面的get方法')
def post(self, request):
return HttpResponse('我是CBV里面的post方法')
# CBV会自动根据请求方式的不同匹配类中定义的方法并自动执行
CBV源码分析
# urls.py下
path('func/', views.MyView.as_view())
# views.py下
from django import views
class MyView(views.View):
def get(self, request):
return HttpResponse('我是CBV里面的get方法')
def post(self, request):
return HttpResponse('我是CBV里面的post方法')
# CBV会自动根据请求方式的不同匹配类中定义的方法并自动执行
源码分析入口
path('func/', views.MyView.as_view())
1. 首先分析自己定义的类中并没有as_view,那么在父类View中找方法as_view
2. 父类中有as_view并且在其 中又定义view并且将view当作返回值返回出去
3. 那么CBV路由匹配的本质也就相当于path('func/', views.view)
父类中的view方法
def view(request, *args, **kwargs):
self = cls(**initkwargs) # cls就等于我们自己定义的类
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.setup(request, *view, **kwargs)
if not hasattr(self, 'request'):
raise AttributeError(
"%s instance has no 'request' attribute. Did you override "
"setup() and forget to call super()?" % cls.__name__
)
return self.dispatch(request, *args, **kwargs)
4. 调用vie函数返回的是self.dispatch(request, *args, **kwargs)
5. 相当于MyView.dispatch(request, *args, **kwargs)
6. 从MyView自身查找dispatch,没有就从父类查找
父类中的 http_method_names列表
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
父类中的dispatch方法
def dispatch(self, request, *args, **kwargs):
# (当前请求方法转为小写字母,假设当前是post请求)判断post在不在http_method_names列表中
if request.method.lower() in self.http_method_names:
# 如果在 从MyView中找到与post对应的功能方法并获取其数据与方法
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
# 然后返回出去
return handler(request, *args, **kwargs)
模板层
模板语法传值
# 方式1 指明道姓传参,减少资源消耗。
return render(request, 'modal.html', {'name':name})
# 方式2 关键字locals(),将整个局部名称空间中的名字全部传入。
return render(request,'modal.html',locals())
模板语法传值范围
-
基本数据类型
可以直接传递使用
-
函数
函数名的传递会自动加括号执行并返回值展示到页面上,
函数如果又参数则不会执行也不会展示,模板语法不支持有参函数
-
类和对象
类名的传递会自动加括号产生对象并展示到页面上
对象传递则直接使用即可
模板语法会判断每一个名字是否可调用,如果可以,则直接调用
django的模板语法在操作容器类型的时候只允许使用句点符
模板语法过滤器
# 类似于python中的内置函数。
1. length,统计长度
<p>统计长度:{{ 数据|length }}</p>
2. add,加法运算还可以将字符串相加进行拼接
<p>加法运算:{{ 整型|add:123 }}、加法运算:{{ 字符串|add:'heiheihei' }}</p>
3. date,日期转换
<p>日期转换:{{ 时间|date:'Y-m-d H:i:s' }}</p>
4. filesizeformat,统计文件大小,自动做单位换算处理
<p>文件大小:{{ file_size|filesizeformat }}</p>
5. slice,数据切片,超出范围取全部
<p>数据切片:{{ l|slice:'0:10' }}</p>
6. truncatechars,字符截取,最后三个点也算在其中
<p>字符截取(三个点算一个):{{ s1|truncatechars:6 }}</p>
7. truncatewords,单词截取,以空格为标准
p>单词截取(空格):{{ s1|truncatewords:6 }}</p>
8. p>语法转义:{{ script_tag|safe }}</p>
<p>语法转义:{{ script_tag1|safe }}</p>
from django.utils.safestring import mark_safe
script_tag1 = '<script>alert(666)</script>'
res = mark_safe(script_tag1)
ps:有时候html页面上的数据不一定非要在html页面上编写了 也可以后端写好传入
'''django模板语法中的符号就两个 一个{{}} 一个{%%}
需要使用数据的时候 {{}}
需要使用方法的时候 {%%}
'''
模板语法标签
# 类似于python的流程控制
# if 判断
{% if 条件 %} 条件一般是模板语法传过来的数据,直接写名字使用即可
条件成立执行的代码
{% elif 条件1 %}
条件1成立执行的代码
{% else %}
条件都不成立执行的代码
{% endif %}
# for循环
{% for i in xxx %}
{{i}}
{{i}}
{% endif %}
# for循环结合if判断一起使用
{% for i in s %}
{% if forloop.first %}
<p>这是第一次哟~</p>
{% elif forloop.last %}
<p>这是最后一次!</p>
{% else %}
<p>{{ i }}</p>
{% endif %}
# 判断是否为空
{% empty %}
<p>你给我的是个空 怎么for循环呢</p>
{% endfor %}
自定义标签函数、过滤器、inclusion_tag
想要自定义,需要先在应用下创建一个名为templatetags文件夹
在该文件夹创建任意名称的py文件,在文件下编写自定义相关的代码
from django.template import Library
register = Library()
自定义过滤器
# 在自定义过滤器上添加 @register.filter(name='myfilter')
@register.filter(name='myfilter')
def my_add(a, b):
return a + b
# 自定义过滤器只能添加俩个形参
自定义标签函数
# 在自定义标签函数上添加 @register.simple_tag(name='mt')
@register.simple_tag(name='mt')
def func(a, b, c, d):
return a + b + c + d
# 函数的形参不做限制
自定义inclusion_tag
# 在自定义inclusion_tag上添加 @register.inclusion_tag(filename='it.html')
@register.inclusion_tag(filename='it.html')
def index(n):
html = []
for i in range(n):
html.append('第%s页'%i)
return locals()
模板的继承
{% extends 'html文件名' %}
{% block 名字 %}
模板内容
{% endblock %}
{% block 名字 %}
子板内容
{% endblock %}
一般情况下母板中至少应该有三个区域使得扩展性更高!!!
css content js
{% block css %}
{% endblock %}
{% block content %}
{% endblock %}
{% block js %}
{% endblock %}
'''子板中还可以使用母板的内容 {{ block.super }} '''
7.模板的导入(了解)
将html页面的某个部分当做模块的形式导入使用
{% include 'menu.html' %}

浙公网安备 33010602011771号