一,类视图
1,类视图介绍
视图是一个可调用的对象,它接收一个请求然后返回一个响应,这个可调用对象可以不只是函数,Django还提供一些可以用作视图的类,叫做类视图。
以函数的形式进行定义的视图就是函数视图,视图函数便于理解,但是遇到一个视图函数对应的路径提供了多种不同的HTTP请求方式的支持时(get,post,delete,put),需要在一个函数中写不同的业务逻辑,代码的可读性和复用性就很低, 所以引入类视图进行解决。
2,使用类视图
①创建一个新的应用进行使用
python manage.py startapp app02
②创建路由

from django.conf.urls import url
from app02.views import *
urlpatterns = [
url(r'^test', TestView.as_view()),
]
③ 在主路由引入

④定义类视图

定义类视图需要导入视图类 View
from django.shortcuts import render, HttpResponse
# 导入视图类
from django.views.generic import View
# Create your views here.
class TestView(View):
def get(self, request):
return HttpResponse('这是GET请求')
def post(self, request):
return HttpResponse('这是POST请求')
测试
d:webdevopsmydjango>curl -X POST http://127.0.0.1:8000/app02/test 杩欐槸POST璇锋眰 d:webdevopsmydjango>curl http://127.0.0.1:8000/app02/test 杩欐槸GET璇锋眰
加参数-X POST为post请求
不加参数默认为getqingq
在windows的cmd请求返回为乱码
使用Postman测试


3,使用类视图实现简单登录
①定义路由

url(r'^login', LoginView.as_view(), name='log'),
②定义类视图

③创建app02的templates文件夹
把登录的页面login.html放入

默认会访问 根目录下的templates的登录页面

在setting把创建的应用加入
否则无法访问 会出现下面提示


页面访问
http://127.0.0.1:8000/app02/login

补充:模板分应用配置
①把对应应用设置在setting

②在应用下新建templates并且在该文件夹下面再创建一个文件夹
然后把页面放入到该文件夹

③修改视图文件

这样配置即使两个templates出现了相同文件名也会找到对应的页面
解释
查看配置文件setting可以找到BASE_DIR为
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
其中__file__代表文件本身,例如本次运行的login.html 如果找的的是跟目录下的login.html即
__file__ == D:webdevopsmydjango emplateslogin.html
os.path.abspath(__file__) 为文件绝对路径即 D:webdevopsmydjango emplateslogin.html
os.path.dirname(os.path.abspath(__file__)) 为改文件所在的文件夹即D:webdevopsmydjango emplates
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))则为文件夹的文件夹即 D:webdevopsmydjango
同理如果找的是应用app02下对应的页面login.html则BASE_DIR为 D:webdevopsmydjangoapp02再通过setting的拼接templates

所以此时运行的跟目录为 D:webdevopsmydjangoapp02 emplates

如果在视图设置如下即可找到正确login.html
即使对应的页面名称有冲突也不会影响找到正确的页面

二,模板语法
1,变量的使用
在模板中,如果想要输出后端传输的变量。需要使用到模板的标签语法。
语法: {{变量名称}}
示例:在后端传入变量到模板中,在模板中调用输出变量。
①定义路由

②定义视图

③在模板中调用输出变量

页面显示

本次变量在视图类已经设置好了 也可以通过web页面传递,修改视图
class TemplateView(View):
def get(self, request):
return render(request, 'app02/tpl.html', {'name': request.GET.get('name')})
页面传递name值
http://127.0.0.1:8000/app02/tpltest?name=linux

2,传递多个变量
当在视图需要往模板传输很多变量时,如果一个一个写,会很繁琐不方便,在框架中提供了,locals方法,可以传递所有变量。
在上面列子视图中,继续进行操作
①使用locals方法

class TemplateView(View):
def get(self, request):
username = 'devops'
dateTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
age = 18
return render(request, 'app02/tpl.html', locals())
②在模板中调用输出变量值

<body>
{{ username }}
当前时间为:{{ dateTime }}
<p>年龄:{{ age }}</p>
</body>
页面显示

list和dict值获取
①插入列表和字典数据

②在模板中调用输出变量

页面输出

获取list或者dict中的其中一个值,可以通过.进行获取。list填写数字下标,dict填写key。

页面显示

3,过滤器
对于通过视图输出到模板中的数据,进行二次的处理。可以通过模板过滤器实现。
语法格式:{{ obj | filter: param }}
常用过滤器
|
过滤器 |
作用 |
实例 |
|
add |
给变量加上对应的值 |
{{ age | add:100}} |
|
capfirst |
首字母大写 |
{{ username | capfirst }}
|
|
cut |
从字符串中移除指定的字符 |
{{ username | cut:'d' }}
|
|
date |
格式化日期字符串 |
{{ day_time | date:'Y-m-d H:i:s' }}
|
|
default |
如果值是False,就替换成设置的默认值,否则就用本来的值 |
{{ hobby | default:'这是一个空列表' }}
|
3,模板控制器
1,判断语句
语法
语法结构:{% if %}...{% endif %} 或{% if %}…{%else%}…{% endif %}:
标签判断一个变量值,如果是ture,即为存在,不为空并且不是false的boolean值,系统则会显示{% if %}和{% endif %}中间的所有内容。
示例

{% if age >= 18 %}
你已成年
{% else %}
你未成年
{% endif %}
注意:通过请求接收到的数字,其实是一个字符串类型
2,循环语句for
语法
语法结构:{%for%}...{%endfor%}
{% for %}标签允许你按顺序遍历一个序列中的各个元素,每次循环模板系统都会渲染{% for %}...{% endfor %}之间的所有内容。
2.1遍历列表
模板标签写法
<!-- for语句 -->
<!-- 遍历列表 -->
<ul>
{% for one in hobby %}
<li>{{ one }}</li>
{% endfor%}
</ul>
<!-- 倒序 -->
<ul>
{% for one in hobby reversed %}
<li>{{ one }}</li>
{% endfor%}
</ul>
<!-- 计数器 -->
<ul>
{% for one in hobby %}
<li>{{ forloop.counter }},{{ one }}</li>
{% endfor%}
</ul>
<ul>
{% for one in hobby %}
<!-- 判断是否第一个元素 -->
{% if forloop.first %}
<li style="color:red">{{ forloop.counter }},{{ one }}</li>
<!-- 判断是否最后一个元素 -->
{% elif forloop.last %}
<li style="color:green">{{ forloop.counter }},{{ one }}</li>
{% else %}
<li>{{ forloop.counter }},{{ one }}</li>
{% endif %}
{% endfor%}
</ul>
<!-- 遍历字典-->
<ul>
{% for key,value in introduce.items %}
<li>{{ key }}:{{ value }}</li>
{% endfor %}
</ul>
</body>
页面显示

四,自定义过滤器
在上面列子中,学习使用了模板中提供的基本过滤器,但是有时候还是不能够满足业务需求。这时,可以选择使用自定义过滤器
自定义过滤器实现的步骤:
①在应用中创建templatetags
②在其中创建任意.py结尾文件
③导入 from django import template 方法
④注册方法 register = template.Library()
⑤通过装饰器的写法 自定义过滤器
示例:实现一个自定义过滤器
①创建模板templatetags
即在对应应用下新建一个文件夹 本次是在应用app02下创建

②在该文件夹创建一个以py结尾的文件

③导入方法

④注册方法

⑤单个参数(使用装饰器register.filter)
from django import template
register = template.Library()
# 单参数过滤器
@register.filter
def filter_add(v1, v2):
return v1 + v2
模板调用

<ul>
<!-- 加载模板 -->
{% load my_tags %}
<!-- 调用 -->
{{ age | filter_add:2}}
</ul>
页面显示
age原始值为17 加上2值为19

如遇到以下问题


⑥多参数(使用装饰器register.simple_tag)

@register.simple_tag
def filter_add2(v1, v2, v3, v4):
return v1 + v2 + v3 + v4
模板调用

页面显示

五,模板继承
在实际业务开发中,进行会使用页面中相同的部分,为了能够使页面模板部分可以复用。可以采用模板继承的方式。
1,传统模板加载
以主机列表为例
①定义url

②静态资源部署

③静态模板引入
由主机列表模板复制过来

注意:需要提前在setting.py中设置好模板路径和静态资源路径
④定义类视图

⑤修改引入静态资源的路径
例如css js对应的路径
查看页面加载效果

按照以上方式,继续快速创建一个用户管理的页面
使用传统模板加载方式的问题:
①公共部分

②修改公共部分之后还需要修改多个页面
再按照以上方法创建一个用户的页面

2,模板继承方式
①编写基本页面
基本页面是复制host.html页面
找到每个页面的独立页面对应代码删除掉 本次对应的是main代码

写入代替代码 body为自定义名称

②继承模板
修改hots.html 把除了刚刚base.html内删除的main代码以外的代码删除只保留main代码


删除代码后未继承时页面显示

模板继承

同理设置用户列表的继承

修改base.html模板把对应链接修改一下

页面显示


补充:点击标签高亮
以上示例点击主机列表和用户列表时不会对应高亮 如果在样式设置了高亮<li class="active">则会一直高亮
在基础模板base.html的<body></body>内增加以下代码
<script>
// 1,获取当前Url
var currentUrl = window.location.pathname
// 2,遍历查看li标签下面的a对应的href 进行url匹配
$('.nav > li > a').each(function(index,item){
$(this).parent().removeClass('active')
// 3,获取href
// console.log($(this).attr('href'))
if($(this).attr('href') == currentUrl) {
$(this).parent().addClass('active')
}
})
</script>
代码解析
#获取当前页面的Url window.location.pathname
如下图所示

遍历nav -> li -> a标签 首先取消所有页面的高亮,如果url于当前点击的url一致 则单独高亮对应的标签
页面显示

