一、视图层
1、FBV与CBV:即函数形式的视图函数与类形式的视图函数。
①CBV特点:视图层可以自动辨析求情方式,来执行对应的代码。
②CBV基本模式:
a、路由层:
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^xoo/', views.Xoo.as_view()) ]
b、视图层:
class Xoo(View): def get(self, request): return render(request, 'xoo_page.html') def post(self, request): return HttpResponse('xoo的post页面')
c、模板层:
<h1 class="text-center">xoo页面</h1> <form action="" method="post"> <input type="submit" class="btn btn-info" value="点击跳转post页面"> </form>
③CBV源码剖析:具体源码可以在pycharm中查看,此处用文字做简略概括。
a、views.Xoo.as_view() ===> 调用类 Xoo 的 as_view() ===> 返回 view.view。
b、通过访问路由触发视图视图函数执行 ===> view.view() ===> 返回 Xoo(**initkwargs).dispatch(request, *args, **kwargs) ===> 返回handler(request, *args, **kwargs)。
c、'GET'与'POST'都可以与handler匹配并转成小写,然后对应的类里面的函数。
二、模板层
1、模板语法之传值取值:
①基本数据类型:可以完整传值
a、视图层:
def xxx(request): t_str = '你妈贵姓' t_int = 3 t_float = 3.3 t_bool = False t_list = [1, 'aaa'] t_tuple = (2, 'bbb') t_set = {3, 'ccc'} t_dict = {'name': 'tom', 'age': 18} t_mix = ['你妈贵姓', 3, 3.3, False, [1, 'aaa'], (2, 'bbb'), {3, 'ccc'}, {'name': 'tom', 'age': 18}] return render(request, 'xxx_page.html', locals())
b、模板层:
<p>{{ t_str }}</p> <p>{{ t_int }}</p> <p>{{ t_float }}</p> <p>{{ t_bool}}</p> <p>{{ t_list }}</p> <p>{{ t_tuple }}</p> <p>{{ t_set }}</p> <p>{{ t_dict }}</p> <p>{{ t_mix }}</p>
②函数,类,对象
a、模板语法会先判断传入的函数或类是否可以直接加括号调用(不用传参且无法传参),若可以调用则直接反馈调用返回值,若不可调用则该条模板语法无效。
b、传入对象本身以及传入可调用类(相当于传入对象)会展示类的__str__方法的返回值。
c、视图层:
def uuu(request): def ddd(): return '函数ddd的返回值' class Xoo: def self_func(self): return 'xoo_obj的self函数的返回值' @classmethod def cls_func(cls): return 'xoo_obj的cls函数的返回值' @staticmethod def static_func(): return 'xoo_obj的static函数的返回值' def __str__(self): return 'xoo_obj的打印效果' xoo_obj = Xoo() return render(request, 'uuu_page.html', locals())
d、模板层:
<p>{{ ddd }}</p> <!--函数ddd的返回值--> <p>{{ Xoo }}</p> <!--xoo_obj的打印效果--> <p>{{ xoo_obj }}</p> <!--xoo_obj的打印效果--> <p>{{ xoo_obj.self_func }}</p> <!--xoo_obj的self函数的返回值--> <p>{{ xoo_obj.cls_func }}</p> <!--xoo_obj的cls函数的返回值--> <p>{{ xoo_obj.static_func }}</p> <!--xoo_obj的static函数的返回值-->
③句点符取值:在模板语法中,索引取值,按照键取值,get方法等都需要换成句点符的形式,如,t_mix = ['你妈贵姓', 3, 3.3, False, [1, 'aaa'], (2, 'bbb'), {3, 'ccc'}, {'name': 'tom', 'age': 18}]。
a、t_mix[0] ===> {{ t_mix.0 }} ===> '你妈贵姓'。
b、t_mix[7]['name'] ===> {{ t_mix.7.name }} ===> 'tom'。
c、t_mix[7].get('age') ===> {{ t_mix.7.age }} ===> 18。
2、模板语法之过滤器取值:
①过滤器方法是模板语法的内置方法,限制最多只能有两个参数,原值与过滤参数。
②基本语法:{{ 原值|过滤器:过滤参数 }}。
③常用过滤器:
a、视图层:
def xxx(request): t_str = '你妈贵姓' t_int = 3 t_bool = False t_size = 123456789 import datetime t_datetime = datetime.datetime.now() t_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] t_lstr = 'abcdefgh' t_info = 'a你好bcd在吗da走了' t_msg = 'aaa 你好 bb 在吗 c 走了 dd 下次 eee 一定' t_tag = '<h1>标题</h1>' from django.utils.safestring import mark_safe t_tag_2 = mark_safe('<h1>标题2</h1>') return render(request, 'xxx_page.html', locals())
b、模板层:
<p>{{ t_str|length }}</p> <!--统计长度 ===> 4 --> <p>{{ t_int|default:'备用值' }}</p> <!--原值为真用原值 ===> 3 --> <p>{{ t_bool|default:'备用值' }}</p> <!--原值为假用备用值 ===> '备用值' --> <p>{{ t_size|filesizeformat }}</p> <!--数字转为文件大小的格式 ===> 117.7 MB --> <p>{{ t_datetime|date:'Y-m-d H:i:s' }}</p> <!--datetime格式的时间转为格式化时间 ===> 2020-05-28 23:33:53 --> <p>{{ t_list|slice:'2:7:2' }}</p> <!--支持列表切片 ===> ['c', 'e', 'g'] --> <p>{{ t_lstr|slice:'2:7:2' }}</p> <!--支持字符串切片 ===> 'ceg' --> <p>{{ t_info|truncatechars:8 }}</p> <!--按照字符个数切,包含默认的三个点 'a你好bc...' ===> --> <p>{{ t_msg|truncatewords:8 }}</p> <!--按照空格隔断的个数切,不包含默认的三个点 ===> 'aaa 你好 bb 在吗 c 走了 dd 下次 ...' --> <p>{{ t_msg|cut:' ' }}</p> <!--移除指定字符 ===> 'aaa你好bb在吗c走了dd下次eee一定' --> <p>{{ t_list|join:'+' }}</p> <!--塞入指定隔断拼接 ===> 'a+b+c+d+e+f+g+h' --> <p>{{ t_str|add:'hahaha' }}</p> <!--累加,字符串与字符串则拼接 ===> '你妈贵姓hahaha' --> <p>{{ t_int|add:20 }}</p> <!--累加,数字与数字则加法运算 ===> 23 --> <p>{{ t_tag }}</p> <!--默认不转义 ===> '<h1>标题</h1>' --> <p>{{ t_tag|safe }}</p> <!--识别html语法 ===> 标题 --> <p>{{ t_tag_2 }}</p> <!--已被标记为safe,识别html语法 ===> 标题2 -->
3、模板语法之逻辑标签:
①视图层:
def xxx(request): t_list = [1, 2, 3, 4, 5, 6] t_age = 22 t_list_2 = ['aaa', 'bb', 'c'] t_dict = {'name': 'tom', 'age': 18} return render(request, 'xxx_page.html', locals())
②模板层:
<p> {% for n in t_list %} {# <span>{{ forloop }}</span> <!--for循环自带的参数forloop,每次循环的值都不同,用于标记循环位置-->#} <span>{{ n }}</span> {% empty %} <!--空可迭代对象时,执行这条后面的--> {% endfor %} <!--结果为 1 2 3 4 5 6 --> </p> <p> {% if t_age < 18 %} <span>要不要叔叔帮你补习功课</span> {% elif t_age < 28 %} <span>领证吗</span> <!--执行这条--> {% else %} <span>阿姨,我想靠自己</span> {% endif %} </p> {% for l in t_list_2 %} {% if l|length < 2 %} <span>太短了,没感觉~</span> {% elif l|length > 2 %} <span>太长了,受不鸟~</span> {% else %} <span>尺寸刚刚好,很舒服~</span> {% endif %} {% endfor %} <!--结果为 太长了,受不鸟~ 尺寸刚刚好,很舒服~ 太短了,没感觉~ --> <p> {% for x in t_dict.keys %} <span>{{ x }}</span> {% endfor %} </p> <!--结果为 'name' 'age' --> <p> {% for y in t_dict.values %} <span>{{ y }}</span> {% endfor %} </p> <!--结果为 'tom' 18 --> <p> {% for z in t_dict.items %} <span>{{ z }}</span> {% endfor %} </p> <!--结果为 ('name', 'tom') ('age', 18) -->
4、模板语法之with...as:把复杂的取值表达式绑定给一个别名,后续可以直接拿别名进行操作,如,视图层---t_mix = ['你妈贵姓', 3, 3.3, False, [1, 'aaa'], (2, 'bbb'), {3, 'ccc'}, {'name': 'tom', 'age': 18}],模板层---{% with t_mix.7.name as t_name %}代码代码代码{% endwith%},但是要注意,别名只在with语法内部有效。
5、自定义过滤器,逻辑标签,inclusion_tag。
①必做前置准备:
a、在app内创建一个名字限定为templatetags的文件夹。
b、在该文件夹内创建任意名称的py文件,如,mytag.py。
c、在该py文件内先书写下面两行固定的语句:
from django import template register = template.Library()
②mytag.py:
# 自定义过滤器 @register.filter(name='my_add') # 过滤器名 def my_add(a, b): # 第一参数是原值,第二是过滤参数 return a + b + b + b # 自定义逻辑标签 @register.simple_tag(name='my_style') def my_style(a, b, c): return '<{}@{}${}>'.format(a, b, c) # 自定义inclusion_tag,定义一个方法,绑定给一个页面,将该方法内的数据传给该页面 # 在新页面通过方法名将绑定页面的渲染效整体果调用在新页面相应的局部位置 @register.inclusion_tag('tag_page.html') def use_tag(n): t_list = [x**2 for x in range(n)] return locals()
③绑定页面:
<span>嘿嘿嘿</span> {% for i in t_list %} <span>{{ i }}</span> {% endfor %}
④模板层:
{% load mytag %} <p>{{ 10|my_add:3 }}</p> <!-- 结果为 19 --> <p>{% my_style '打' '扰' '了' %}</p> <!--结果为 <打@扰$了> --> {% use_tag 3 %} <!--结果为 嘿嘿嘿 0 1 4 -->
6、模板的继承:
①现有一个已编辑好的页面father.html,另有若干个页面需要形成跟该页面整体类似,只有局部不一样的效果,那么可以起一个空白页面,开头书写上{% extends 'father.html' %},如此书写的页面会完全复制father.html的html语句。
②此时再在father.html中定位到需要变更的区域,开头结尾分别插入{% block area_name %}变更区{% endblock %},如此,子页面就不会复制变更区的html语句,可以在子页面中按照{% block area_name %}子页面特定局部内容{% endblock %}的方式书写,则会在变更区呈现自己另写的内容,如此便实现了全局相似,局部变更的效果。
③基于此,可以分别将css,js,html写成变更区:{% block css_area_name %}css语句{% endblock %},{% block js_area_name %}js语句{% endblock %},{% block html_area_name %}html语句{% endblock %},如此便可以实现即减少了重复代码,又不失灵活拓展。
④可以在变更区里写{{ block.super }}来重用父页面的内容,甚至可以写多个。
7、模板的导入:将某个页面整体导入到另一个页面的局部,在需要导入的局部位置书写 ===> {% include 'good_page.html' %} 即可。