Day02 url和模板
1. URL
URL地址说明:
url(regex, view, kwargs=None, name=None)
(正则,视图函数,关键字参数,名字)
使用url给视图函数传参数
在url配置中将正则部分小括号括起来。比如:
url(r'^time/plus/(\d{1,2})/$', views.hours_ahead)
#一个小括号可以传一个参数,\d表示数字,{1,2}表示一到两位数字
如果有多个参数则用/隔开,参数需要用分组,比如:
url(r'^time/plus/(\d{1,2})/(\d{1,2})/$', views.hours_ahead),
给参数命名,使用正则分组的别名,比如:
url(r'^time/plus/(?P<time1>\d{1,2})/(?P<time2>\d{1,2})/$', views.hours_ahead)
#?P<time1>表示该分组的名字是time1,使用分组别名之后,视图函数的参数必须用分组的别名,但是位置可以不固定。
给url取别名,那么在调用此url的地方可以使用别名。比如:
url(r'^buy/$', views.buy, name='buy'),
url(r'^login/$', views.login, name='login'),
2. 反向解析
# django中正常访问顺序是总项目url--》app的url--》视图函数--》调用模板
#反向解析是模板--》调用urls和视图函数
#传参时,url、视图函数、html里的传参数量要一致,要对应。
在视图函数中,反向解析url,即#在函数中重新调用url:
from django.shortcuts import render, redirect
from django.urls import reverse
def buy(request):
#'index'是指name为index的url
return redirect(reverse('index'))
#位置参数args用来传参 args=[2]是一个参数2,args=[2,3]是两个参数
return redirect(reverse('detail', args=[2]))
#另一种传参方式,kwargs里的key值要和detail函数中的参数名一致,用这种传参方式必须要在url里给分组命名,名字也一致
return redirect(reverse('detail', kwargs={"first": 2,"second":5}))
在templates中,使用别名:
{% url 'detail' stu.id %}
#表示跳转到name为detail的url
#stu.id 是用来传参的,传到前面的url=detail,这时候app下的urls要对应地传参,如url(r'^detail/(\d+)$',detail,name='detail')。同时detail函数下面也要有一个参数(个数是对应地)来接收。。
如:
def detail(request,d):
grade = Grade.objects.get(id=d)
return render(request,'hello/detail.html',{'grade':grade})
使用命名空间:
在工程的urls.py文件中,在include时,可以指定命名空间,更加细化的划分url。相当于给app.urls命名了。比如:
url(r'^App/', include('App.urls', namespace='App')),
#指定命令空间后,使用反向解析时需要加上命名空间,比如:
在视图函数中: return redirect(reverse('students:index'))
在templates中: {% url 'students:detail' %}
3. 模板
在Django框架中,模板是可以帮助开发者快速生成呈现给用户页面的工具
模板的设计方式实现了我们MVT中VT的解耦,VT有着N:M的关系,一个V可以调用任意T,一个T可以供任意V使用
模板处理分为两个过程
加载
渲染
模板主要有两个部分
HTML静态代码
模板语言,动态插入的代码段(挖坑,填坑)
模板中的动态代码段除了做基本的静态填充,还可以实现一些基本的运算,转换和逻辑
模板中的变量: 视图传递给模板的数据,遵守标识符规则
语法: {{ var }}
如果变量不存在,则插入空字符串
python manage.py shell: 进入Python环境, 且会自动导入Django配置,建议使用
>>> python manage.py shell # 进入python环境
>>> from django import template
>>> c = template.Context({'name': 'Nige'})
>>> t = template.Template('My name is {{ name }}.')#调用key
>>> print (t.render(c))
My name is Nige.
模板中的点语法
字典查询
>>> from django.template import Template, Context
>>> person = {'name': 'Sally', 'age': '43'}
>>> c = Context({'person': person})
>>> t = Template('{{ person.name }} is {{ person.age }} years old.')
>>> t.render(c)
'Sally is 43 years old.'
属性或者方法
>>> from django.template import Template, Context
>>> import datetime
>>> d = datetime.date(2017, 5, 2)
>>> d.year
2017
>>> d.month
5
>>> d.day
2
>>> c = Context({'date': d})
>>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
>>> t.render(c)
'The month is 5 and the year is 2017.'
>>> from django.template import Template, Context
>>> class Person(object):
... def __init__(self, first_name, last_name):
... self.first_name, self.last_name = first_name, last_name#赋值
>>> c = Context({'person': Person('John', 'Smith')})
>>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')
>>> t.render(c)
'Hello, John Smith.'
方法不能有参数。
>>> from django.template import Template, Context
>>> c = Context({'var': 'hello'})
>>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')
>>> t.render(c)
'hello -- HELLO -- False' 大写--不是数字
>>> t.render(Context({'var': '123'}))
'123 -- 123 -- True'
列表,使用索引,不允许负索引
>>> from django.template import Template, Context
>>> c = Context({'items': ['apples', 'bananas', 'carrots']})
>>> t = Template('i have a {{ items.2 }}.')#Python中是items[2]
>>> t.render(c)
'i have a carrots.'
模板中的小弊端,调用对象的方法,不能传递参数
模板中的标签
语法 {% tag %}
作用
1. 加载外部传入的变量
2. 在输出中创建文本
3. 控制循环或逻辑
#if 语句:
#格式: 要加endif,其他的基本上一样
if单分支
{% if 表达式 %}
语句
{% endif %}
if双分支
{% if 表达式 %}
语句
{% else %}
语句
{% endif %}
if多分支
{% if 表达式 %}
语句
{% elif 表达式 %}
语句
{% else %}
语句
{% endif %}
判断true或false
{% if today_is_weekend %}
<p>Welcome to the weekend!</p>
{% endif %}
使用 and or not,可结合使用,and和or中 and具有更高优先权。
{% if athlete_list and coach_list %}
<p>Both athletes and coaches are available.</p>
{% endif %}
{% if not athlete_list %}
<p>There are no athletes.</p>
{% endif %}
{% if athlete_list or coach_list %}
<p>There are some athletes or some coaches.</p>
{% endif %}
{% if not athlete_list or coach_list %}
<p>There are no athletes or there are some coaches.</p>
{% endif %}
{% if athlete_list and not coach_list %}
<p>There are some athletes and absolutely no coaches.</p>
{% endif %}
使用多个相同的逻辑操作关键字也是允许的,比如:
{% if athlete_list or coach_list or parent_list or teacher_list %}
使用 in和not in,
{% if "bc" in "abcdef" %}
This appears since "bc" is a substring of "abcdef"
{% endif %}
{% if user not in users %}
If users is a list, this will appear if user isn't an element of the list.
{% endif %}
使用 is 和 is not#这个有点不一样
{% if somevar is True %}
This appears if and only if somevar is True.
{% endif %}
{% if somevar is not None %}
This appears if somevar isn't None.
{% endif %}
#for 语句:
{% for 变量 in 列表 %}
语句1
{% empty %}
语句2
{% endfor %}
## 当列表为空或不存在时,执行empty之后的语句
{% for item in todo_list %}
<p>{{ forloop.counter }}: {{ item }}</p>
{%endfor %}
##{{ forloop.counter }} 表示当前是第几次循环,从1数数
{{ forloop.counter0}}表示当前是第几次循环,从0数数
{{ forloop.revcounter}}表示当前是第几次循环,倒着数数,到1停
{{ forloop.revcounter0}}表示当前第几次循环,倒着数,到0停
{{ forloop.first }} 判断是否是第一个 布尔值
{{ forloop.last }} 是否是最后一个 布尔值
{{ forloop.parentloop.counter }} 取到上一层循环的计数
{% for like in likes %}
{% if forloop.first %}
<P style="color: brown">
{% elif forloop.last %}
<p style="color: blue">
{% endif %}
{{ like }}|{{ forloop.counter }}
</p># 注意这里,循环里可以拆分标签
{% endfor %}
{% for link in links %}
{{ link }}{% if not forloop.last %} | {% endif %}
{% endfor %}
forloop.parentloop
<table border="1" cellspacing="0" width="500">
#边框长度为1,层数为0,宽度为500
{% for country in countries %}
<tr>
{% for city in country %}
<td>country{{ forloop.parentloop.counter }}</td>#取到上一层循环的计数
<td>
{{ city }} {{ forloop.counter }}#每个循环的计数
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
注释:
单行注释
{# 被注释掉的内容 #}
多行注释
{% comment %}
内容
{% endcomment %}
过滤器:
{{ var|过滤器 }}
作用:在变量显示前修改
add {{ value|add:2 }}
没有减法过滤器,但是加法里可以加负数
{{ value|add:-2 }}
lower
{{ name|lower }}
upper
{{ my_list|first|upper }}#取到my_list里第一个元素,并转为大写
截断:
{{ bio|truncatechars:30#字符数 }}
#过滤器可以传递参数,参数需要使用引号引起来
比如join: {{ students|join:'=' }}#在字符串中加字符
{#类似于Python中的 str.join(students) #}
默认值:default,格式 {{var|default:'value'}} {{var|default:students}}、{{var|default:12321}}
#如果变量没有被提供或者为False,空,会使用默认值
根据指定格式转换日期为字符串,处理时间的
就是针对date进行的转换
{{ dateVal | date:'y-m-d H-i-s' }}#python中时分秒是H-M-S
HTML转义
将接收到的数据当成普通字符串处理还是当成HTML代码来渲染的一个问题
渲染成html:{{ code|safe }}#一般不会写这个safe,直接执行Javascript脚本,很危险,黑客常用XSS脚本
关闭自动转义
{% autoescape off%}
code
{% endautoescape %}
打开自动转义转义#默认是转义的,即转为字符串,一般打开这个
{% autoescape on%}
code
{% endautoescape %}
模板继承
block:挖坑
{% block XXX%}
code
{% endblock %}
extends 继承,写在开头位置
{% extends '父模板路径' %}
include: 加载模板进行渲染
{% include '模板文件' %}
模版继承和bootstrap的使用
# 在工程目录下新建一个templates文件夹,要在settings中改一下55行TEMPLATES=[{
'DIRS':[os.path.join(BASE_DIR,'templates')]
}]#表示取到templates的路径
# 新建一个base.html当做基模板
<head>
<meta charset="UTF-8">
<title>{% block title %}title{% endblock %}</title>
#bootstrap的起步-css核心文件
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
{% block header %}
{# <div style="width: 100%;height: 100px;background: orange;"></div>#}#自定义宽高#一般头部和尾部不会改动
#Bootstrap的组件--导航栏
{% include 'nav.html' %}#代码比较多,于是新建了一个html放代码,用include加载
{% endblock %}
{% block content %}
<div>
content
</div>
{% endblock %}
{% block footer %}
<div>footer</div>
{% endblock %}
#bootstrap的起步-jquery核心插件,bootstrap所有的js插件都依赖于jQuery,所以要放在前面。
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
#bootstrap的起步-js核心插件
<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
#继承模板 app/templates/app/block.html
{% extends 'base.html' %}#写在开头,表示继承自base.html
{% block title %}#可以改title代码块
首页
{% endblock %}