day02 Django: url view controller function template templates views
A .Django: url controller
Django1 and Django2 only difference is this: the version of the syntax routing layer (URLconf): it is backwards compatible
The role of 1.urls.py
Mapping between request path and view function
2. Simple routing configuration:
2.1 unknown packets: packet by acquiring dynamic data on the url, corresponding to the position parameter
from django.conf.urls import url
urlpatterns = [
url(r'^admin/$', admin.site.urls),
url (r '^ articles / 2003 / $', views.special_case_2003), # nothing to say exact match
url (r '^ articles / (\ d {4}) / $', views.year_group_archive), #year_group_archive (request, 2006) the data packet is a default parameter,
url (r '^ articles / (\ d {4}) / (\ d {2}) / $', views.month_archive), data #month_archive (request, 2006,12) is a parameter default packet, packet The default parameter is a parameter
]
2.2 famous groups: group name to the corresponding keyword parameters (P <name> pattern?)
url(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$',views.month_archive) #month_archive(request,year=2006,month=12)
3. Note:
1. To get a value in the url, only to place a pair of parentheses around it
2. do not need to add a leading slash, can not add, because Django has given us a good plus
3.r '' is optional, but suggested adding that tells python string is 'original'
4.r '' behind the slash inside a bit mean, when distribution: Not like without
4. Distribution
Problem Description: If a project has many applications, each application url lot, this time url are written in a global urls.py not appropriate
How to solve: include: distribution interfaces provided by Django
4.1. Urls.py master file
from django.conf.urls import url
from django.urls import include, path
from app01 import views
urlpatterns = [
url (r '^ $', views.index), #r '^ $': matching the root path
url(r'^app01/', include('app01.urls')),
url(r'^app02/', include('app02.urls')),
]
4.2. To app01 application, for example, from urls.py file
from django.conf.urls import url, include
from app01 import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/(\d{4})/$', views.year_group_archive),
url(r'^articles/(\d{4})/(\d{2})/$', views.month_archive),
]
5.反向解析
问题描述: 如果你url里面写好了路径,之后你需要改这个路径的名字,那么与之关联的路径名都要改,很麻烦
如何解决: 使用url()的name参数, 给当前url起个别名, 与之关联的东西使用这个别名: 之后只要改urls.py中的路径,其他关联的自己更新
url(r'^login.html/', views.login, name='aliasLogin'), #urls.py文件: 起个别名
<form action="{% url 'aliasLogin' %}" method="post"> #html文件: 使用"{% url 'aliasLogin' %}"去urls.py中找最新的url,这个过程就叫做反向解析
二.Django: 视图函数
1.request:请求对象
def index(request):
print(request.method) #请求方式
print(request.path) #请求路径
print(request.POST) #POST请求时的数据: 字典格式
print(request.GET) #GET请求时的数据: 字典格式
print(request.META) #请求头里的信息
print(request.get_full_path()) #除了路径,参数也可以取出来
print(request.is_ajax()) #判断是不是ajax发的,浏览器发的就是false
return HttpResponse('ok')
2.response:响应对象
共有3种形式,Django对于请求最后一定相应的是HttpPResponse的实例对象
2.1.HttpResponse('字符串')
2.2.render(request, '页面')
功能一: 把'页面'的内容读出来,返回
功能二: 嵌入变量
render()里面加入第三个参数{}, 把html中的数据名称和变量对应起来
def index(request): #views.py文件
var = '苹果'
name = '八戒'
return render(request, 'index.html', {'shop': var, 'name': name})
<body> #html文件
<h3>商品信息</h3>
<p>{{ shop }}</p>
<p>{{ name }}</p>
</body>
2.3.redirect('路径') 重定向
比如登录页面: 登录成功重定向到首页,让浏览器多发一次请求
return render(request, 'index.html', {'shop': var, 'name': name}) #问题一: 不能刷新,一刷新就变成登录界面 问题二: 因为是直接打开文件,html不能使用render的第三个参数
return redirect('/index/') #redirect()可解决上面的两个问题
三.Django:模板templates
模板语法, 是由render()来渲染的
1.{{ var }} 用来渲染变量的
1.1.var的数据类型可以是: 字符串,数字,列表,元祖,字典,也可以是对象,还可以是标签
1.2.深度查询: 使用句点符号
列表,元组,字典: 直接用句点来深度查询
对象: 模板里调方法,不能加括号,有参数怎么办, 那就调不了; 这里调用后得到的是函数里的返回值
def index(request): #views.py文件
name = '八戒'
age = 19
lst = ['bajie', 'wukong', 'datang']
tup = ('bajie', 'wukong', 'datang')
dic = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
class Animal(object):
def __init__(self, name, age):
self.name = name
self.age = age
def running(self):
return 'running'
bajie = Animal('bajie', 18)
wukong = Animal('wukong', 10)
datang = Animal('datang', 16)
person_list = [bajie, wukong, datang]
#return render(request, 'index.html', {'name': name, 'age': age, 'lst': lst, 'dic': dic, }) #也可以用locals()代替{}传参
return render(request, 'index.html', locals())
<body>
<p>this is 模板语法</p> #html文件
<h4>{{ name }}
{{ age }}
{{ lst }}
{{ tup }}
{{ tup.2 }}
{{ lst.2 }}
{{ dic }}
{{ dic.k1 }}
{{ person_list }}
{{ person_list.2.name }}
{{ person_list.2.running }}
</h4>
</body>
1.3.过滤器 filter
语法: {{ var|filter_name:参数 }}
def index(request): #views.py文件
import datetime
now = datetime.datetime.now()
book_list = ['xiyou', 'dahua', 'dongyou']
file_size = 123210
var = 'mynameisbajie'
artical = 'abcd efg hig klmn opq rstuvw xyz, zkl olm nil abc ink shell.'
tag = "<script>alert(123)</script>"
link = "<a href='http://www.baidu.com/'>点我</a>"
return render(request, 'index.html', locals())
<body> #html文件
<p>过滤器</p>
<h4>{{ now|date:"Y-m-d" }} #日期过滤器
{{ book_list|default:"没有符合条件的数据" }} #默认过滤器: 如果没有值得话, 设置默认显示的内容
{{ book_list|length }} #长度
{{ file_size|filesizeformat }} #格式化大小
{{ var|slice:"2:-1" }} #切片
{{ artical|truncatechars:10 }} #截字符: 截取前几个字符,还要预留3个给 ...
{{ artical|truncatewords:5 }} #截取单词: 截取前几个单词,不用预留给 ...
{{ link }} #没有在浏览器渲染出来, 因为你给浏览器的是特殊符号(哪来的,Django给转义的)组成的文本,而不是标签, 怎么办?
{{ tag }} #Django为了安全考虑,因为你的数据是从数据库取到的,有可能是用户写的恶意标签数据: xss攻击
{{ link|safe }} #安全过滤器: 在确认你的标签是安全的情况下: 告诉Django按标签处理,不需要转义
</h4>
</body>
2.{% %} 用来渲染标签的
2.1.for 循环标签 {% for %}
def index(request): #views.py文件
book_list = ['xiyou', 'dahua', 'dongyou']
return render(request, 'index.html', locals())
<body>
<p>渲染标签</p> #html文件
<ul>
{% for book in book_list %} #for的语法只能这样,没有break,continue啥的
<li>{{ forloop.first }} {{ forloop.counter }} {{ book }}</li> #forloop只能在这里用, 计数器; forloop.first返回布尔值
{% endfor %}
</ul>
</body>
2.2.if 标签 {% if %}
def index(request): #views.py文件
age = 22
class Animal(object):
def __init__(self, name, age):
self.name = name
self.age = age
def running(self):
return 'running'
bajie = Animal('bajie', 18)
wukong = Animal('wukong', 10)
datang = Animal('datang', 16)
person_list = [bajie, wukong, datang]
return render(request, 'index.html', locals())
<body>
<p>渲染标签</p> #html文件
{% if age > 50 %} #if 的使用
<p>50</p>
{% else %}
<p>{{ age }}</p>
{% endif %}
{% for person in person_list %} #if 与 for的组合使用
{% if person.age > 17 %}
<p>{{ person.name }} {{ person.age }}</p>
{% endif %}
{% endfor %}
</body>
2.3.with 起个别名 {% with %}
当.句点语法比较长的是时候可以考虑用这个
<p>
{% with person_list.2.name as name %}
{{ name }}
{% endwith %}
</p>
2.4.csrf_token {% csrf_token %}
这个标签用于跨站请求'伪造保护'
当不写这句的时候, 提交POST请求会被Forbidden掉
那么{% csrf_token %}这个究竟做了什么?
给form表单搞了个通行证: <input type="hidden" name="csrfmiddlewaretoken" value="4en0Q7Q9xUyb11LicKltEUuQ4mmP1LXSsX2Ik9LGz9XB14T2WJHiewcpM23QSrTp">
作用是什么?
forbidden那些上来就直接给我发POST请求的非法人, 使用中间件来验证
3.模板的继承extend {% extends 'base.html' %} (extend 延伸)
我们需要一个母版, 当有相同结构的网页时, 可以继承这个母版
3.1.目前我们向服务器发送请求的三种方式
一.浏览器的地址栏直接输入url
二.form表单里的action, 可以是GET,POST
三.a标签, 是最常用的方式
3.2.母版的使用: 首页,订单,和商品列表三个页面有 80% 以上的代码重复了, 怎么办? 给它们三个找个母版
3.2.1.母版中:
保留重复的代码
个性的代码用{% block content %} {% endblock %}占位
base.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
*{margin: 0; padding: 0;}
.header{width: 100%; height: 50px;}
</style>
</head>
<body>
<div class="header"></div>
<div class="container">
<div class="row">
<div class="col-md-3">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Panel title</h3>
</div>
<div class="panel-body">
<p><a href="/index/">首页</a></p>
<p><a href="/order/">订单</a></p>
<p><a href="/shopping/">商品列表</a></p>
</div>
</div>
</div>
<div class="col-md-9">
{% block content %}
{% endblock %}
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
</body>
</html>
3.2.2.每个页面: 使用render()进行渲染时
先使用{% extends 'base.html' %}引进母版中保留的代码
再使用{% block content %} {% endblock %}编写自己个性的代码
index.html
{% extends 'base.html' %}
{% block content %}
<div class="jumbotron">
<h1>Hello, world!</h1>
<p>...</p>
<p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
</div>
{% endblock %}
order.html
{% extends 'base.html' %}
{% block content %}
{% for order in order_list %}
<p>{{ order }}</p>
{% endfor %}
{% endblock %}
shopping.html
{% extends 'base.html' %}
{% block content %}
{% for shopping in shopping_list %}
<p>{{ shopping }}</p>
{% endfor %}
{% endblock %}
3.2.3.{% block content %} {% endblock %}占位的盒子里面也可以有默认的内容, 需要的时候,再进行覆盖,使我们的代码无限灵活
3.3.模板继承注意事项
1.当在模板中使用 {% extends 'base.html' %} 时, 必须是第一个标签, 否则模板继承无法使用
2.在母版中设置的 {% block %} 越多越好,多一点钩子总比少一点好
3.{{ block.super }} 变量可以直接使用,代表的是母版中被占位的标签
4.{% block content %} {% endblock content%} 首位呼应,增加易读性
5.一个母版中 block标签的名字不能重复