Web开发基础之Django二
一,类视图
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:\web\devops\mydjango>curl -X POST http://127.0.0.1:8000/app02/test 杩欐槸POST璇锋眰 d:\web\devops\mydjango>curl http://127.0.0.1:8000/app02/test 杩欐槸GET璇锋眰
加参数-X POST为post请求
不加参数默认为get请求
在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:\web\devops\mydjango\templates\login.html
os.path.abspath(__file__) 为文件绝对路径即 D:\web\devops\mydjango\templates\login.html
os.path.dirname(os.path.abspath(__file__)) 为改文件所在的文件夹即D:\web\devops\mydjango\templates\
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))则为文件夹的文件夹即 D:\web\devops\mydjango\
同理如果找的是应用app02下对应的页面login.html则BASE_DIR为 D:\web\devops\mydjango\app02再通过setting的拼接templates
所以此时运行的跟目录为 D:\web\devops\mydjango\app02\templates
如果在视图设置如下即可找到正确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一致 则单独高亮对应的标签
页面显示