WEB框架-Django框架学习(一)-基础层级关系

今日主要内容为Django架构,主要有路由层,视图层和模板层php

1. Django的路由层

URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于客户端发来的某个URL调用哪一段逻辑代码对应执行。css

1.1 普通路由控制

普通路由控制就是咱们就是最经常使用的打开urls文件,告诉Django,客户端调用某个URL就调用哪一段逻辑代码来对应执行。html

from django.urls import path,re_path

from app01 import views

urlpatterns = [
path('admin/', admin.site.urls),
path('timer/',views.timer),
path('login.html/',views.login,name= 'Log'),
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),
]

这个就是咱们普通路由控制,告诉django去那里执行什么代码。python

注意:这个时候就有无名分组的定义,若是想要从url中捕获固定的参数,只须要在它周围放置一对圆括号,而无名分组就至关于位置参数。 不须要添加一个前导的反斜杠,由于每一个URL 都有。例如,应该是^articles 而不是 ^/articles。 每一个正则表达式前面的'r' 是可选的可是建议加上。它告诉Python 这个字符串是“原始的” —— 字符串中任何字符都不该该转义 。web

1.2 有名分组

为了捕获固定的参数,在参数前加入“?p<参数>”,就至关于关键字参数ajax

上面的示例使用简单的、没有命名的正则表达式组(经过圆括号)来捕获URL 中的值并以位置 参数传递给视图。在更高级的用法中,可使用命名的正则表达式组来捕获URL 中的值并以关键字 参数传递给视图。 在Python 正则表达式中,命名正则表达式组的语法是(?Ppattern),其中name 是组的名称,pattern 是要匹配的模式。 下面是以上URLconf 使用命名组的重写:正则表达式

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/(?P<year>[0-9]{4})/$', views.year_archive),
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]

不过上面有名分组有一些要注意的点数据库

  • 视图函数在调用路由层的变量,须要使用相同的名字,位置变换没有关系
  • url有几个分组,视图函数必需要接收几个参数

这个实现与前面的示例彻底相同,只有一个细微的差异:捕获的值做为关键字参数而不是位置参数传递给视图函数。例如:django

/articles/2005/03/ 请求将调用views.month_archive(request, year='2005', month='03')函数,而不是views.month_archive(request, '2005', '03')。
/articles/2003/03/03/ 请求将调用函数views.article_detail(request, year='2003', month='03', day='03')。

1.3 路由分发

在往后APP数量逐渐的增长,单个app的路由没有办法继续服务,这个时候在项目顶层的urls就至关于顶层urls,在判断前面的url后丢给APP自身的urls判断路由。减小顶层urls的工做量。浏览器

在顶层路由层的设置

from django.contrib import admin
from django.urls import path,re_path,include

urlpatterns = [
    # 顶层urls
    path("app01/",include("app01.urls")),
    path("app02/",include("app02.urls"))
]

在APP内的分路由层

#APP01
from django.urls import path,re_path,include
from app01 import views


urlpatterns = [
    path('time/',views.timer)
]

#APP02
from django.urls import path,re_path,include
from app02 import views


urlpatterns = [
    path('time/',views.timer)
]

在各自APP内处理本身的逻辑,展现页面

1.4 反向解析

反向解析,对于一个web应用,他的web应用的url不会一成不变,这个时候若是须要更换的话,就须要更改内部关联的url,那么为了更好的管理,这个时候就须要反向解析,反向解析分为俩种。

1.4.1 模板层的反向解析

下面开始演示模板层的反向解析

(1).在urls中设定路由,同时为这条路由设定别名

image_thumb1

(2).在模板层html网页中,设定action路径,设定为{% url ‘路由别名’%}

image_thumb3

(3).在网页中显示,f12发现action已经更改成/login/了。

image_thumb5

(4).在返回urls中修改路由,可是别名不动

image_thumb9

(5).从新启动网页,按f12咱们发现action已经更改成“/login123/”,见证奇迹,之后再变动网页url,只须要在路由层变动后,其余会自动跟着变动。

image_thumb111

其余类型:

  • 位置传参(无名分组){% url 'name' arg1 arg2 ... %}
  • 关键字传参(有名分组){% url 'name' key1=val1 key2=val2 ... %}

1.4.2 在python中的反向解析

下面开始演示python中的反向解析

(1)首先引用

from django.urls import reverse
from django.shortcuts import render,redirect
用reverse解析出要跳转的网页,而后用redirect来跳转到指定的网页

image_thumb13

这样咱们在前面urls更改后,仍是会跳转到指定的网页中!

(2)带参数的引用

对于参数的引用与在模板层中一致

当命名你的URL 模式时,请确保使用的名称不会与其它应用中名称冲突。若是你的URL 模式叫作comment,而另一个应用中也有一个一样的名称,当你在模板中使用这个名称的时候不能保证将插入哪一个URL。在URL 名称中加上一个前缀,好比应用的名称,将减小冲突的可能。咱们建议使用myapp-comment 而不是comment。

1.5 命名空间

命名空间(英语:Namespace)是表示标识符的可见范围。一个标识符可在多个命名空间中定义,它在不一样命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,由于已有的定义都处于其它命名空间中。 因为name没有做用域,Django在反解URL时,会在项目全局顺序搜索,当查找到第一个name指定URL时,当即返回 咱们在开发项目时,会常用name属性反解出URL,当不当心在不一样的app的urls中定义相同的name时,可能会致使URL反解错误,为了不这种事情发生,引入了命名空间。

2 Django的视图层

2.1 视图函数

一个视图函数,简称视图,是一个简单的Python 函数,它接受Web请求而且返回Web响应。响应能够是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片. . . 是任何东西均可以。不管视图自己包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你的Python目录下面。除此以外没有更多的要求了——能够说“没有什么神奇的地方”。为了将代码放在某处,约定是将视图放置在项目或应用程序目录中的名为views.py的文件中。 下面是一个返回当前日期和时间做为HTML文档的视图:

from django.urls import reverse
from django.shortcuts import render,redirect,HttpResponse

# Create your views here.

def current_datatime(request):
    import datetime
    ctime = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % ctime
    return HttpResponse(html)

让咱们逐行阅读上面的代码:

  • 首先,咱们从 django.shortcuts模块导入了HttpResponse类,以及Python的datetime库。

  • 接着,咱们定义了current_datetime函数。它就是视图函数。每一个视图函数都使用HttpRequest对象做为第一个参数,而且一般称之为request

    注意,视图函数的名称并不重要;不须要用一个统一的命名方式来命名,以便让Django识别它。咱们将其命名为current_datetime,是由于这个名称可以精确地反映出它的功能。

     

  • 这个视图会返回一个HttpResponse对象,其中包含生成的响应。每一个视图函数都负责返回一个HttpResponse对象。

视图层,熟练掌握两个对象便可:请求对象(request)和响应对象(HttpResponse)

2.2 HttpRequest对象

2.2.1 request的属性

django将请求报文中的请求行、首部信息、内容主体封装成 HttpRequest 类中的属性。 除了特殊说明的以外,其余均为只读的。

1.HttpRequest.GET
  一个相似于字典的对象,包含 HTTP GET 的全部参数。详情请参考 QueryDict 对象。

   request.GET.get("key") # 推荐写法

   request.GET.getlist("key") # 返回一个多值的列表

   request.GET["key"] # 不推荐,会报错

 

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")

    request.POST.get("key") # 推荐写法

    request.POST.getlist("key") # 返回一个多值的列表

    request.POST["key"] # 不推荐,会报错

3.HttpRequest.body
  一个字符串,表明请求报文的主体。在处理非 HTTP 形式的报文时很是有用,例如:二进制图片、XML,Json等。
  可是,若是要处理表单数据的时候,推荐仍是使用 HttpRequest.POST 。

4.HttpRequest.path
  一个字符串,表示请求的路径组件(不含域名,没有ip以及端口)。
  例如:"/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。

2.2.2 request的方法

request经常使用方法

1.HttpRequest.get_full_path()
  返回 path,若是能够将加上查询字符串,主要是和。
  例如:"/music/bands/the_beatles/?print=true"
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') 装饰你的视图以让响应可以正确地缓存。

2.3 HttpResponse对象

响应对象主要是如下三种方式

  1. HttpResponse("想要显示的内容")

  2. render(request, "模板名称", [ 可选参数])

  3. redirect("要跳转的URL地址")

(1.)HttpResponse()括号内直接跟一个具体的字符串做为响应体,比较直接很简单,因此这里主要介绍后面两种形式。
(2.) render()的参数

request: 用于生成响应的请求对象。
template_name:要使用的模板的完整名称,可选的参数
context:添加到模板上下文的一个字典。默认是一个空字典。若是字典中的某个值是可调用的,视图将在渲染模板以前调用它。
render方法就是将一个模板页面中的模板语法进行渲染,最终渲染成一个html页面做为响应体。

(3.) redirect()重定向其余网页

key:两次请求 

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页面错误信息,访问流量白白丧失;再者某些注册了多个域名的
    网站,也须要经过重定向让访问这些域名的用户自动跳转到主站点等。

3. Django的模板层

3.1 模板语法之变量

在 Django 模板中遍历复杂数据结构的关键是句点字符, 语法:

{{ var_name }}

views.py

def index(request):
    import datetime
    s="hello"
    l=[111,222,333]    # 列表
    dic={"name":"yuan","age":18}  # 字典
    date = datetime.date(1993, 5, 2)   # 日期对象
 
    class Person(object):
        def __init__(self,name):
            self.name=name
 
    person_yuan=Person("yuan")  # 自定义类对象
    person_egon=Person("egon")
    person_alex=Person("alex")
 
    person_list=[person_yuan,person_egon,person_alex]
 
 
    return render(request,"index.html",{"l":l,"dic":dic,"date":date,"person_list":person_list})

template

<h4>{{s}}</h4>
<h4>列表:{{ l.0 }}</h4>
<h4>列表:{{ l.2 }}</h4>
<h4>字典:{{ dic.name }}</h4>
<h4>日期:{{ date.year }}</h4>
<h4>类对象列表:{{ person_list.0.name }}</h4>

注意:句点符也能够用来引用对象的方法(无参数方法):

<h4>字典:{{ dic.name.upper }}</h4>

3.2 模板语法之过滤器

语法:{{obj|filter__name:param}}

default:若是一个变量是false或者为空,使用给定的默认值。不然,使用变量的值。例如:

{{ value|default:"nothing" }}

length:

length:返回值的长度。它对字符串和列表都起做用。例如:
{{ value|length }}
若是 value 是 ['a', 'b', 'c', 'd'],那么输出是 4。

filesizeformat:

filesizeformat:将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等):
例如:
{{ value|filesizeformat }}
若是 value 是 123456789,输出将会是 117.7 MB。

data:

date:若是 value=datetime.datetime.now()
{{ value|date:"Y-m-d" }}

truncatechars:

truncatechars:若是字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
参数:要截断的字符数
例如:{{ value|truncatechars:10 }}

safe:(用的超级多)

Django的模板中会对HTML标签和JS等语法标签进行自动转义,缘由显而易见,这样是为了安全。可是有的时候咱们可能不但愿这些HTML元素被转义,好比咱们作一个内容管理系统,后台添加的文章中是通过修饰的,这些修饰多是经过一个相似于FCKeditor编辑加注了HTML修饰符的文本,若是自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,若是是一个单独的变量咱们能够经过过滤器“|safe”的方式告诉Django这段代码是安全的没必要转义。好比:
value="<a href="">点击</a>"
{{ value|safe }}

3.3 模板之标签

标签看起来像是这样的: {% tag %}。标签比变量更加复杂:一些在输出中建立文本,一些经过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。一些标签须要开始和结束标签 (例如{% tag %} ...标签 内容 ... {% endtag %})。

3.3.1 for标签

做用:遍历每个元素:

{% 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)
forloop.counter0           The current iteration of the loop (0-indexed)
forloop.revcounter         The number of iterations from the end of the loop (1-indexed)
forloop.revcounter0        The number of iterations from the end of the loop (0-indexed)
forloop.first              True if this is the first time through the loop
forloop.last               True if this is the last time through the loop

3.3.2 for…empty

for 标签带有一个可选的{% empty %} 从句,以便在给出的组是空的或者没有被找到时,能够有所操做。

{% for person in person_list %}
    <p>{{ person.name }}</p>

{% empty %}
    <p>sorry,no person here</p>
{% endfor %}

3.3.3 if标签

{% if %}会对一个变量求值,若是它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。

{% if num > 100 or num < 0 %}
    <p>无效</p>
{% elif num > 80 and num < 100 %}
    <p>优秀</p>
{% else %}
    <p>凑活吧</p>
{% endif %}

3.3.4 with标签

使用一个简单地名字缓存一个复杂的变量,当你须要使用一个“昂贵的”方法(好比访问数据库)不少次的时候是很是有用的

例如:

{% with total=business.employees.count %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

3.3.5 csrf_token

这个标签用于跨站请求伪造保护

3.4 自定义标签与过滤器

一、在settings中的INSTALLED_APPS配置当前app,否则django没法找到自定义的simple_tag.

二、在app中建立templatetags模块(模块名只能是templatetags)

三、建立任意 .py 文件,如:my_tags.py

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

{% load my_tags %}

五、使用simple_tag和filter(如何调用)

-------------------------------.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 %}

3.5 模板继承(extend)

Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可让您建立一个基本的“骨架”模版,它包含您站点中的所有元素,而且能够定义可以被子模版覆盖的 blocks 。

经过从下面这个例子开始,能够容易的理解模版继承:

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="style.css" />
    <title>{% block title %}My amazing site{%/span> 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 %} 中。

  • 若是须要从父模板获取块的内容,block.super变量将完成此操做。若是要添加到父块的内容中而不是彻底重写父块,则此选项很是有用。使用block.super插入的数据不会自动转义),由于它已经在父模板中转义

  • 为了更好的可读性,你也能够给你的 {% endblock %} 标签一个 名字 。例如:

    {% block content %}
    
    ...
    
    {% endblock content %}

    在大型模版中,这个方法帮你清楚的看到哪个  {% block %} 标签被关闭了。

     

  • 不能在一个模版中定义多个相同名字的 block 标签。
a