URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于客户端发来的某个URL调用哪一段逻辑代码对应执行php
1 from django.conf.urls import url 2 3 urlpatterns = [ 4 url(正则表达式, views视图函数,参数,别名), 5 ]
from django.urls import path,re_path from app01 import views urlpatterns = [ re_path(r'^articles/2003/$', views.special_case_2003), re_path(r'^articles/([0-9]{4})/$', views.year_archive), re_path(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), re_path(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), ]
注意:css
^articles
而不是 ^/articles
。
在Python 正则表达式中,命名正则表达式组的语法是(?P<name>pattern)
,其中name
是组的名称,pattern
是要匹配的模式。html
下面是以上URLconf 使用命名组的重写:前端
1 from django.urls import path,re_path 2 3 from app01 import views 4 5 urlpatterns = [ 6 re_path(r'^articles/2003/$', views.special_case_2003), 7 re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), 8 re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), 9 re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail), 10 ] 11 #捕获到的数据都是str类型 12 #视图函数里能够指定默认值 13 14 url('blog/$', views.blog), 15 url('blog/?(?P<num>[0-9]{1})', views.blog), 16 def blog(request,num=1): 17 print(num) 18 return HttpResponse('ok')
Django1.1版本的分发python
from django.conf.urls import url,include 程序员
#主urls from django.urls import path,re_path,include from app01 import views from app01 import urls urlpatterns = [ # re_path(r'^app01/',include('app01.urls')),#行 # re_path(r'^app01/&',include('app01.urls')),#不行 # path('app01/',include('app01.urls')),#行 #path('app01/', include(urls)), ]
from django.urls import path,re_path from app01 import views urlpatterns = [ re_path(r'^test/(?P<year>[0-9]{2})/$',views.url_test), ]
在使用Django 项目时,一个常见的需求是得到URL 的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等)。人们强烈但愿不要硬编码这些URL(费力、不可扩展且容易产生错误)或者设计一种与URLconf 绝不相关的专门的URL 生成机制,由于这样容易致使必定程度上产生过时的URL。ajax
在须要URL 的地方,对于不一样层级,Django 提供不一样的工具用于URL 反查:正则表达式
from django.urls import reverse()函数
from django.urls import path,re_path from app01 import views urlpatterns = [ re_path(r'^test/(?P<year>[0-9]{2})/(?P<month>[0-9]{2})/$',views.url_test,name='test'), ]
html代码:数据库
<a href="{% url 'test' 10 23 %}">哈哈</a> django
from django.shortcuts import render, HttpResponse,redirect,reverse def url_test(request,year,month): print(year) print(month) url=reverse('test',args=(10,20)) print(url) return HttpResponse('ok')
总结:1 在html代码里{% url "别名" 参数 参数%}
2 在视图函数中:
2.1 url=reverse('test')
2.2 url=reverse('test',args=(10,20))
当命名你的URL 模式时,请确保使用的名称不会与其它应用中名称冲突。若是你的URL 模式叫作comment
,而另一个应用中也有一个一样的名称,当你在模板中使用这个名称的时候不能保证将插入哪一个URL。在URL 名称中加上一个前缀,好比应用的名称,将减小冲突的可能。咱们建议使用myapp-comment
而不是comment
。
命名空间(英语:Namespace)是表示标识符的可见范围。一个标识符可在多个命名空间中定义,它在不一样命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,由于已有的定义都处于其它命名空间中。
from django.urls import path,re_path,include urlpatterns = [ path('app01/', include('app01.urls')), path('app02/', include('app02.urls')) ]
from django.urls import path,re_path from app01 import views urlpatterns = [ re_path(r'index/',views.index,name='index'), ]
from django.urls import path, re_path, include from app02 import views urlpatterns = [ re_path(r'index/', views.index,name='index'), ]
def index(request): url=reverse('index') print(url) return HttpResponse('index app01')
def index(request): url=reverse('index') print(url) return HttpResponse('index app02')
这样都找index,app01和app02找到的都是app02的index
如何处理?在路由分发的时候指定名称空间
总urls.py在路由分发时,指定名称空间
path('app01/', include(('app01.urls','app01'))), path('app02/', include(('app02.urls','app02')))
url(r'app01/',include('app01.urls',namespace='app01')), url(r'app02/',include('app02.urls',namespace='app02'))
url(r'app01/',include(('app01.urls','app01'))), url(r'app02/',include(('app02.urls','app02')))
在视图函数反向解析的时候,指定是那个名称空间下的
url=reverse('app02:index') print(url) url2=reverse('app01:index') print(url2)
在模版里:
<a href="{% url 'app02:index'%}">哈哈</a>
Django 视图层
一个视图函数,简称视图,是一个简单的Python 函数,它接受Web请求而且返回Web响应。响应能够是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片. . . 是任何东西均可以。不管视图自己包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你的Python目录下面。除此以外没有更多的要求了——能够说“没有什么神奇的地方”。为了将代码放在某处,约定是将视图放置在项目或应用程序目录中的名为views.py的文件中。
下面是一个返回当前日期和时间做为HTML文档的视图:
from django.shortcuts import render, HttpResponse, HttpResponseRedirect, redirect import datetime def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
让咱们逐行阅读上面的代码:
首先,咱们从 django.shortcuts模块导入了HttpResponse类,以及Python的datetime库。
接着,咱们定义了current_datetime函数。它就是视图函数。每一个视图函数都使用HttpRequest对象做为第一个参数,而且一般称之为request。
注意,视图函数的名称并不重要;不须要用一个统一的命名方式来命名,以便让Django识别它。咱们将其命名为current_datetime,是由于这个名称可以精确地反映出它的功能。
这个视图会返回一个HttpResponse对象,其中包含生成的响应。每一个视图函数都负责返回一个HttpResponse对象。
django将请求报文中的请求行、首部信息、内容主体封装成 HttpRequest 类中的属性。 除了特殊说明的以外,其余均为只读的
''' 1.HttpRequest.GET 一个相似于字典的对象,包含 HTTP GET 的全部参数。详情请参考 QueryDict 对象。 2.HttpRequest.POST 一个相似于字典的对象,若是请求中包含表单数据,则将这些数据封装成 QueryDict 对象。 POST 请求能够带有空的 POST 字典 —— 若是经过 HTTP POST 方法发送一个表单,可是表单中没有任何的数据,QueryDict 对象依然会被建立。 所以,不该该使用 if request.POST 来检查使用的是不是POST 方法;应该使用 if request.method == "POST" 另外:若是使用 POST 上传文件的话,文件信息将包含在 FILES 属性中。 注意:键值对的值是多个的时候,好比checkbox类型的input标签,select标签,须要用: request.POST.getlist("hobby") 3.HttpRequest.body 一个字符串,表明请求报文的主体。在处理非 HTTP 形式的报文时很是有用,例如:二进制图片、XML,Json等。 可是,若是要处理表单数据的时候,推荐仍是使用 HttpRequest.POST 。 4.HttpRequest.path 一个字符串,表示请求的路径组件(不含域名)。 例如:"/music/bands/the_beatles/" 5.HttpRequest.method 一个字符串,表示请求使用的HTTP 方法。必须使用大写。 例如:"GET"、"POST" 6.HttpRequest.encoding 一个字符串,表示提交的数据的编码方式(若是为 None 则表示使用 DEFAULT_CHARSET 的设置,默认为 'utf-8')。 这个属性是可写的,你能够修改它来修改访问表单数据使用的编码。 接下来对属性的任何访问(例如从 GET 或 POST 中读取数据)将使用新的 encoding 值。 若是你知道表单数据的编码不是 DEFAULT_CHARSET ,则使用它。 7.HttpRequest.META 一个标准的Python 字典,包含全部的HTTP 首部。具体的头部信息取决于客户端和服务器,下面是一些示例: 取值: CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。 CONTENT_TYPE —— 请求的正文的MIME 类型。 HTTP_ACCEPT —— 响应可接收的Content-Type。 HTTP_ACCEPT_ENCODING —— 响应可接收的编码。 HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。 HTTP_HOST —— 客服端发送的HTTP Host 头部。 HTTP_REFERER —— Referring 页面。 HTTP_USER_AGENT —— 客户端的user-agent 字符串。 QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。 REMOTE_ADDR —— 客户端的IP 地址。 REMOTE_HOST —— 客户端的主机名。 REMOTE_USER —— 服务器认证后的用户。 REQUEST_METHOD —— 一个字符串,例如"GET" 或"POST"。 SERVER_NAME —— 服务器的主机名。 SERVER_PORT —— 服务器的端口(是一个字符串)。 从上面能够看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 以外,请求中的任何 HTTP 首部转换为 META 的键时, 都会将全部字母大写并将链接符替换为下划线最后加上 HTTP_ 前缀。 因此,一个叫作 X-Bender 的头部将转换成 META 中的 HTTP_X_BENDER 键。 8.HttpRequest.FILES 一个相似于字典的对象,包含全部的上传文件信息。 FILES 中的每一个键为<input type="file" name="" /> 中的name,值则为对应的数据。 注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的状况下才会 包含数据。不然,FILES 将为一个空的相似于字典的对象。 9.HttpRequest.COOKIES 一个标准的Python 字典,包含全部的cookie。键和值都为字符串。 10.HttpRequest.session 一个既可读又可写的相似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用。 完整的细节参见会话的文档。 11.HttpRequest.user(用户认证组件下使用) 一个 AUTH_USER_MODEL 类型的对象,表示当前登陆的用户。 若是用户当前没有登陆,user 将设置为 django.contrib.auth.models.AnonymousUser 的一个实例。你能够经过 is_authenticated() 区分它们。 例如: if request.user.is_authenticated(): # Do something for logged-in users. else: # Do something for anonymous users. user 只有当Django 启用 AuthenticationMiddleware 中间件时才可用。 ------------------------------------------------------------------------------------- 匿名用户 class models.AnonymousUser django.contrib.auth.models.AnonymousUser 类实现了django.contrib.auth.models.User 接口,但具备下面几个不一样点: id 永远为None。 username 永远为空字符串。 get_username() 永远返回空字符串。 is_staff 和 is_superuser 永远为False。 is_active 永远为 False。 groups 和 user_permissions 永远为空。 is_anonymous() 返回True 而不是False。 is_authenticated() 返回False 而不是True。 set_password()、check_password()、save() 和delete() 引起 NotImplementedError。 New in Django 1.8: 新增 AnonymousUser.get_username() 以更好地模拟 django.contrib.auth.models.User。 */
''' 1.HttpRequest.get_full_path() 返回 path,若是能够将加上查询字符串。 例如:"/music/bands/the_beatles/?print=true" 注意和path的区别:http://127.0.0.1:8001/order/?name=lqz&age=10 2.HttpRequest.is_ajax() 若是请求是经过XMLHttpRequest 发起的,则返回True,方法是检查 HTTP_X_REQUESTED_WITH 相应的首部是不是字符串'XMLHttpRequest'。 大部分现代的 JavaScript 库都会发送这个头部。若是你编写本身的 XMLHttpRequest 调用(在浏览器端),你必须手工设置这个值来让 is_ajax() 能够工做。 若是一个响应须要根据请求是不是经过AJAX 发起的,而且你正在使用某种形式的缓存例如Django 的 cache middleware, 你应该使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 装饰你的视图以让响应可以正确地缓存。 '''
响应对象主要有三种形式:
HttpResponse()括号内直接跟一个具体的字符串做为响应体,比较直接很简单,因此这里主要介绍后面两种形式。
1
2
3
|
render(request, template_name[, context])
结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。
|
参数: request: 用于生成响应的请求对象。 template_name:要使用的模板的完整名称,可选的参数 context:添加到模板上下文的一个字典。默认是一个空字典。若是字典中的某个值是可调用的,视图将在渲染模板以前调用它。
render方法就是将一个模板页面中的模板语法进行渲染,最终渲染成一个html页面做为响应体。
传递要重定向的一个硬编码的URL
def my_view(request): ... return redirect('/some/url/')
也能够是一个完整的URL:
def my_view(request): ... return redirect('http://www.baidu.com/')
1)301和302的区别。 301和302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址能够从响应的Location首部中获取 (用户看到的效果就是他输入的地址A瞬间变成了另外一个地址B)——这是它们的共同点。 他们的不一样在于。301表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向以后的网址; 302表示旧地址A的资源还在(仍然能够访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。 SEO302好于301 2)重定向缘由: (1)网站调整(如改变网页目录结构); (2)网页被移到一个新地址; (3)网页扩展名改变(如应用须要把.php改为.Html或.shtml)。 这种状况下,若是不作重定向,则用户收藏夹或搜索引擎数据库中旧地址只能让访问客户获得一个404页面错误信息,访问流量白白丧失;再者某些注册了多个域名的 网站,也须要经过重定向让访问这些域名的用户自动跳转到主站点等。 重定向301和302的区别
向前端返回一个json格式字符串的两种方式
# 第一种方式 # import json # data={'name':'lqz','age':18} # data1=['lqz','egon'] # return HttpResponse(json.dumps(data1)) # 第二种方式 from django.http import JsonResponse # data = {'name': 'lqz', 'age': 18} data1 = ['lqz', 'egon'] # return JsonResponse(data) return JsonResponse(data1,safe=False)
CBV基于类的视图(Class base view)和FBV基于函数的视图(Function base view)
from django.views import View class AddPublish(View): def dispatch(self, request, *args, **kwargs): print(request) print(args) print(kwargs) # 能够写相似装饰器的东西,在先后加代码 obj=super().dispatch(request, *args, **kwargs) return obj def get(self,request): return render(request,'index.html') def post(self,request): request return HttpResponse('post')
print(request.FILES) print(type(request.FILES.get('file_name'))) file_name=request.FILES.get('file_name').name from django.core.files.uploadedfile import InMemoryUploadedFile with open(file_name,'wb')as f: for i in request.FILES.get('file_name').chunks(): f.write(i)
Django 模版层
你可能已经注意到咱们在例子视图中返回文本的方式有点特别。 也就是说,HTML被直接硬编码在 Python代码之中。
def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
尽管这种技术便于解释视图是如何工做的,但直接将HTML硬编码到你的视图里却并非一个好主意。 让咱们来看一下为何:
对页面设计进行的任何改变都必须对 Python 代码进行相应的修改。 站点设计的修改每每比底层 Python 代码的修改要频繁得多,所以若是能够在不进行 Python 代码修改的状况下变动设计,那将会方便得多。
Python 代码编写和 HTML 设计是两项不一样的工做,大多数专业的网站开发环境都将他们分配给不一样的人员(甚至不一样部门)来完成。 设计者和HTML/CSS的编码人员不该该被要求去编辑Python的代码来完成他们的工做。
程序员编写 Python代码和设计人员制做模板两项工做同时进行的效率是最高的,远胜于让一我的等待另外一我的完成对某个既包含 Python又包含 HTML 的文件的编辑工做。
基于这些缘由,将页面的设计和Python的代码分离开会更干净简洁更容易维护。 咱们可使用 Django的 模板系统 (Template System)来实现这种模式,这就是本章要具体讨论的问题
python的模板:HTML代码+模板语法
def current_time(req): # ================================原始的视图函数 # import datetime # now=datetime.datetime.now() # html="<html><body>如今时刻:<h1>%s.</h1></body></html>" %now # ================================django模板修改的视图函数 # from django.template import Template,Context # now=datetime.datetime.now() # t=Template('<html><body>如今时刻是:<h1>{{current_date}}</h1></body></html>') # #t=get_template('current_datetime.html') # c=Context({'current_date':str(now)}) # html=t.render(c) # # return HttpResponse(html) #另外一种写法(推荐) import datetime now=datetime.datetime.now() return render(req, 'current_datetime.html', {'current_date':str(now)[:19]})
模版语法重点:
变量:{{ 变量名 }}
1 深度查询 用句点符
2 过滤器
标签:{{% % }}
在 Django 模板中遍历复杂数据结构的关键是句点字符, 语法:{{变量名}}
def template_test(request): name = 'lqz' li = ['lqz', 1, '18'] dic = {'name': 'lqz', 'age': 18} ll2 = [ {'name': 'lqz', 'age': 18}, {'name': 'lqz2', 'age': 19}, {'name': 'egon', 'age': 20}, {'name': 'kevin', 'age': 23} ] ll3=[] class Person: def __init__(self, name): self.name = name def test(self): print('test函数') return 11 @classmethod def test_classmethod(cls): print('类方法') return '类方法' @staticmethod def static_method(): print('静态方法') return '静态方法' lqz = Person('lqz') egon = Person('egon') person_list = [lqz, egon] bo = True te = test() import datetime now=datetime.datetime.now() link1='<a href="https://www.baidu.com">点我<a>' from django.utils import safestring link=safestring.mark_safe(link1) # html特殊符号对照表(http://tool.chinaz.com/Tools/htmlchar.aspx) # 这样传到前台不会变成特殊字符,由于django给处理了 dot='♠' # return render(request, 'template_index.html', {'name':name,'person_list':person_list}) return render(request, 'template_index.html', locals())
<p>{{ name }}</p> <p>{{ li }}</p> <p>{{ dic }}</p> <p>{{ lqz }}</p> <p>{{ person_list }}</p> <p>{{ bo }}</p> <p>{{ te }}</p> <hr> <h3>深度查询句点符</h3> <p>{{ li.1 }}</p> <p>{{ dic.name }}</p> <p>{{ lqz.test }}</p> <p>{{ lqz.name }}</p> <p>{{ person_list.0 }}</p> <p>{{ person_list.1.name }}</p> <hr> <h3>过滤器</h3> {#注意:冒号后面不能加空格#} <p>{{ now | date:"Y-m-d H:i:s" }}</p> {#若是变量为空,设置默认值,空数据,None,变量不存在,都适用#} <p>{{ name |default:'数据为空' }}</p> {#计算长度,只有一个参数#} <p>{{ person_list |length }}</p> {#计算文件大小#} <p>{{ 1024 |filesizeformat }}</p> {#字符串切片,前闭后开,前面取到,后面取不到#} <p>{{ 'hello world lqz' |slice:"2:-1" }}</p> <p>{{ 'hello world lqz' |slice:"2:5" }}</p> {#截断字符,至少三个起步,由于会有三个省略号(传负数,1,2,3都是三个省略号)#} <p>{{ '刘清政 world lqz' |truncatechars:"4" }}</p> {#截断文字,以空格作区分,这个不算省略号#} <p>{{ '刘清政 是 大帅比 谢谢' |truncatewords:"1" }}</p> <p>{{ link1 }}</p> <p>{{ link1|safe }}</p> <p>{{ link }}</p> <p>♠</p> <p>{{ dot }}</p> {#add 能够加负数,传数字字符串均可以#} <p>{{ "10"|add:"-2" }}</p> <p>{{ li.1|add:"-2" }}</p> <p>{{ li.1|add:2 }}</p> <p>{{ li.1|add:"2" }}</p> <p>{{ li.1|add:"-2e" }}</p> {#upper#} <p>{{ name|upper }}</p> <p>{{ 'LQZ'|lower }}</p> <hr> <h3>模版语法之标签</h3> {#for 循环 循环列表,循环字典,循环列表对象#} <ui> {% for foo in dic %} {{ foo }} {% endfor %} {#也能够混用html标签#} {% for foo in li %} <ul>foo</ul> {% endfor %} </ui> {#表格#} <table border="1"> {% for foo in ll2 %} <tr> <td>{{ foo.name }}</td> <td>{{ foo.age }}</td> </tr> {% endfor %} </table> <table border="1"> {#'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 4, 'revcounter0': 3, 'first': True, 'last': False}#} {% for foo in ll2 %} <tr> <td>{{ forloop.counter }}</td> <td>{{ foo.name }}</td> <td>{{ foo.age }}</td> </tr> {% endfor %} </table> {% for foo in ll5 %} <p>foo.name</p> {% empty %} <p>空的</p> {% endfor %} <hr> <h3>if判断</h3> {% if name %} <a href="">hi {{ name }}</a> <a href="">注销</a> {% else %} <a href="">请登陆</a> <a href="">注册</a> {% endif %} {#还有elif#} <hr> <h3>with</h3> {% with ll2.0.name as n %} {{ n }} {% endwith %} {{ n }} {% load my_tag_filter %} {{ 3|multi_filter:3 }} {#传参必须用空格区分#} {% multi_tag 3 9 10 %} {#能够跟if连用#} {% if 3|multi_filter:3 > 9 %} <p>大于</p> {% else %} <p>小于</p> {% endif %}
注意:句点符也能够用来引用对象的方法(无参数方法):
<h4>字典:{{ dic.name.upper }}<
/
h4>
语法: {{obj|filter__name:param}} 变量名字|过滤器名称:变量
default
若是一个变量是false或者为空,使用给定的默认值。不然,使用变量的值。例如:
{{ value|default:"nothing" }}
返回值的长度。它对字符串和列表都起做用。例如: {{ value|length }} 若是 value 是 ['a', 'b', 'c', 'd'],那么输出是 4。
filesizeformat
将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB'
, '4.1 MB'
, '102 bytes'
, 等等)。例如: {{ value|filesizeformat }} 若是 value
是 123456789,输出将会是 117.7 MB
。
若是 value=datetime.datetime.now()
{{ value|date:"Y-m-d" }}
若是 value="hello world" {{ value|slice:"2:-1" }}
若是字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
参数:要截断的字符数
例如: {{ value|truncatechars:9 }}
Django的模板中会对HTML标签和JS等语法标签进行自动转义,缘由显而易见,这样是为了安全。可是有的时候咱们可能不但愿这些HTML元素被转义,好比咱们作一个内容管理系统,后台添加的文章中是通过修饰的,这些修饰多是经过一个相似于FCKeditor编辑加注了HTML修饰符的文本,若是自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,若是是一个单独的变量咱们能够经过过滤器“|safe”的方式告诉Django这段代码是安全的没必要转义。好比: value="<a href="">点击</a>" {{ value|safe}}
标签看起来像是这样的: {% tag %}
。标签比变量更加复杂:一些在输出中建立文本,一些经过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。一些标签须要开始和结束标签 (例如{% tag %} ...
标签 内容 ... {% endtag %})。
遍历每个元素:
{% for person in person_list %} <p>{{ person.name }}</p> {% endfor %}
能够利用{% for obj in list reversed %}反向完成循环。
遍历一个字典:
{% for key,val in dic.items %} <p>{{ key }}:{{ val }}</p> {% endfor %}
注:循环序号能够经过{{forloop}}显示
forloop.counter The current iteration of the loop (1-indexed) 当前循环的索引值(从1开始)
forloop.counter0 The current iteration of the loop (0-indexed) 当前循环的索引值(从0开始)
forloop.revcounter The number of iterations from the end of the loop (1-indexed) 当前循环的倒序索引值(从1开始)
forloop.revcounter0 The number of iterations from the end of the loop (0-indexed) 当前循环的倒序索引值(从0开始)
forloop.first True if this is the first time through the loop 当前循环是否是第一次循环(布尔值)
forloop.last True if this is the last time through the loop 当前循环是否是最后一次循环(布尔值)
forloop.parentloop 本层循环的外层循环
for 标签带有一个可选的{% empty %} 从句,以便在给出的组是空的或者没有被找到时,能够有所操做。
{% for person in person_list %} <p>{{ person.name }}</p> {% empty %} <p>sorry,no person here</p> {% endfor %}
{% if %}会对一个变量求值,若是它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。
{% if num > 100 or num < 0 %} <p>无效</p> {% elif num > 80 and num < 100 %} <p>优秀</p> {% else %} <p>凑活吧</p> {% endif %}
if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。
使用一个简单地名字缓存一个复杂的变量,当你须要使用一个“昂贵的”方法(好比访问数据库)不少次的时候是很是有用的
例如:
{% with total=business.employees.count %}
{{ total }} employee{{ total|pluralize }}
{% endwith %}
不要写成as
{% csrf_token%}
这个标签用于跨站请求伪造保护
一、在settings中的INSTALLED_APPS配置当前app,否则django没法找到自定义的simple_tag.
二、在app中建立templatetags模块(模块名只能是templatetags)
三、建立任意 .py 文件,如:my_tags.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
from django import template
from django.utils.safestring import mark_safe
register = template.Library() #register的名字是固定的,不可改变
@register . filter
def filter_multi(v1,v2):
return v1 * v2
<br>
@register .simple_tag
def simple_tag_multi(v1,v2):
return v1 * v2
<br>
@register .simple_tag
def my_input( id ,arg):
result = "<input type='text' id='%s' class='%s' />" % ( id ,arg,)
return mark_safe(result)
|
四、在使用自定义simple_tag和filter的html文件中导入以前建立的 my_tags.py
1
|
{ % load my_tags % }
|
五、使用simple_tag和filter(如何调用)
1
2
3
4
5
6
7
8
9
10
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .html
{ % load xxx % }
# num=12
{{ num|filter_multi: 2 }} #24
{{ num|filter_multi: "[22,333,4444]" }}
{ % simple_tag_multi 2 5 % } 参数不限,但不能放在 if for 语句中
{ % simple_tag_multi num 5 % }
|
注意:filter能够用在if等语句后,simple_tag不能够
{% if num|filter_multi:30 > 100 %} {{ num|filter_multi:30 }} {% endif %}
语法:{% include '模版名称' %}
如:{% include 'adv.html' %}
<div class="adv"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Panel title</h3> </div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-danger"> <div class="panel-heading"> <h3 class="panel-title">Panel title</h3> </div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-warning"> <div class="panel-heading"> <h3 class="panel-title">Panel title</h3> </div> <div class="panel-body"> Panel content </div> </div> </div> adv.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> {# <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">#} <style> * { margin: 0; padding: 0; } .header { height: 50px; width: 100%; background-color: #369; } </style> </head> <body> <div class="header"></div> <div class="container"> <div class="row"> <div class="col-md-3"> {% include 'adv.html' %} </div> <div class="col-md-9"> {% block conn %} <h1>你好</h1> {% endblock %} </div> </div> </div> </body> </html> base.html
{% extends 'base.html' %}
{% block conn %}
{{ block.super }}
是啊
{% endblock conn%}
order.html
Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可让您建立一个基本的“骨架”模版,它包含您站点中的所有元素,而且能够定义可以被子模版覆盖的 blocks 。
经过从下面这个例子开始,能够容易的理解模版继承:
<!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="style.css"/> <title>{% block title %}My amazing site{% endblock %}</title> </head> <body> <div id="sidebar"> {% block sidebar %} <ul> <li><a href="/">Home</a></li> <li><a href="/blog/">Blog</a></li> </ul> {% endblock %} </div> <div id="content"> {% block content %}{% endblock %} </div> </body> </html>
这个模版,咱们把它叫做 base.html
, 它定义了一个能够用于两列排版页面的简单HTML骨架。“子模版”的工做是用它们的内容填充空的blocks。
在这个例子中, block
标签订义了三个能够被子模版内容填充的block。 block
告诉模版引擎: 子模版可能会覆盖掉模版中的这些位置。
子模版可能看起来是这样的:
{% extends "base.html" %} {% block title %}My amazing blog{% endblock %} {% block content %} {% for entry in blog_entries %} <h2>{{ entry.title }}</h2> <p>{{ entry.body }}</p> {% endfor %} {% endblock %}
extends
标签是这里的关键。它告诉模版引擎,这个模版“继承”了另外一个模版。当模版系统处理这个模版时,首先,它将定位父模版——在此例中,就是“base.html”。
那时,模版引擎将注意到 base.html
中的三个 block
标签,并用子模版中的内容来替换这些block。根据 blog_entries
的值,输出可能看起来是这样的:
<!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="style.css" /> <title>My amazing blog</title> </head> <body> <div id="sidebar"> <ul> <li><a href="/">Home</a></li> <li><a href="/blog/">Blog</a></li> </ul> </div> <div id="content"> <h2>Entry one</h2> <p>This is my first entry.</p> <h2>Entry two</h2> <p>This is my second entry.</p> </div> </body> </html>
请注意,子模版并无定义 sidebar
block,因此系统使用了父模版中的值。父模版的 {% block %}
标签中的内容老是被用做备选内容(fallback)。
这种方式使代码获得最大程度的复用,而且使得添加内容到共享的内容区域更加简单,例如,部分范围内的导航。
这里是使用继承的一些提示:
若是你在模版中使用 {% extends %}
标签,它必须是模版中的第一个标签。其余的任何状况下,模版继承都将没法工做。
在base模版中设置越多的 {% block %}
标签越好。请记住,子模版没必要定义所有父模版中的blocks,因此,你能够在大多数blocks中填充合理的默认内容,而后,只定义你须要的那一个。多一点钩子总比少一点好。
若是你发现你本身在大量的模版中复制内容,那可能意味着你应该把内容移动到父模版中的一个 {% block %}
中。
If you need to get the content of the block from the parent template, the {{ block.super }}
variable will do the trick. This is useful if you want to add to the contents of a parent block instead of completely overriding it. Data inserted using {{ block.super }}
will not be automatically escaped (see the next section), since it was already escaped, if necessary, in the parent template.
为了更好的可读性,你也能够给你的 {% endblock %}
标签一个 名字 。例如:
1
2
3
|
{ % block content % }
...
{ % endblock content % }
|
在大型模版中,这个方法帮你清楚的看到哪个 {% block %}
标签被关闭了。
block
标签。