Django从入门到放弃一

参考地址:http://www.cnblogs.com/yuanchenqi/articles/7629939.html

一、什么是Django

  Django是一个Web应用程序的框架。

  预备知识:1、python基础    2、数据库    3、前端( jquey + bootstrap )

 

1.1、Django请求生命周期

 

二、Web请求的本质

    CS架构:client   —   server        #客户端 — 服务端
    BS架构:browser  —  server     #浏览器 — 服务端

 

三、MTV模型

   代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。与数据库交互

   代表模板(Template): 负责如何把页面(根据请求,决定给用户什么样的页面)展示给用户(HTML)。

   代表视图(View): 负责业务逻辑,并在适当的时候调用Model和Template(把数据封装成模板的样子返还给用户)

图解MTV模型:

  URL控制器:什么路径 ( login | admin | index 等) 交给什么函数去处理。

 

四、Django学习过程

4.1、下载与命令  — 在命令行操作的方式  ( django是依赖于Python库的,用什么pip版本下载的,django就存在于对应版本的Python库的Scripts目内[django-admin.exe] )

  下载:        pip3 install django==1.11.1    #最新版本django-2.1.4

  卸载:        pip3 uninstall django-1.11.1  

  创建项目:django-admin startproject mysite    #其中mysite为项目名称(项目名可以修改)

  创建一个应用:python3 manage.py startapp app01  #app01为应用名称

  项目启动命令:python3 manage.py runserver  IP+PORT   #默认是127.0.0.1:8000

                  mysite 项目包含的:

                       1 — mysite     #和项目名称同名的目录(不能更改名称)

                             — settings    项目配置文件

                             — urls           路径与视图函数的映射关系

                             — wsgi         封装的socket

                      2 — manage.py     Django项目进行交互的脚本

                      3 — app01 项目应用   #python3 manage.py startapp app01(创建一个应用)

                             — models     数据库操作

                             — views        视图函数

                      4 — app02 项目应用   #python3 manage.py startapp app02(创建一个应用)

                             — models     数据库操作

                             — views        视图函数

                     5 — templates   #存放模板的文件夹(名称必须为templates)

                             — index.html

                             — login.html

 

4.3、查看django版本号  pip show django

 

4.4、在pycharm中创建Django项目的方式

方式一:使用现有的Python(版本)环境

方式二:创建一个新的Python虚拟环境

make available to all projects:表示创建的项目工程可以被其他项目使用

inherit global site-packages:继承本地的Python版本库

  五.URL控制器  urls.py — Django实践  

  URL:  协议://IP(域名):端口(80)/路径?GET参数

  URL的功能:反映URL的路径和视图函数的映射关系

  5.1、URL的简单使用 — 在urls.py文件配置

from app01 import views  # 指定路径

urlpatterns = [
    url(r'^timer/', views.timer),   #views.timer(request) django会帮我们把http请求头的信息拿到,默认传进去。
]

  然后在应用目录APP01的views.py文件里,定义timer

from django.shortcuts import render,HttpResponse
# HttpResponse为封装响应体的类

def timer(request):  # request请求信息对象
    import time
    ctime=str(time.time())
    return HttpResponse(ctime)   # 执行timer函数,[HttpResponse这个类在实例化的时候需要传入的值为字符串类型,所以ctime要设置为字符串类型]

访问:http://127.0.0.1:8000/timer/ 拿到当前机器的时间!

 

5.2、URL的无名分组 —  一般用来传URL路径里面的某一个参数,或者说是获取URL路径里面的某一个参数。

# 在urils.py里对应的配置。
from app01 import views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^articles/(\d{4})/$', views.article_year),    
]                                                       
# \d{4}:表示4位数字
# (\d{4}) :表示接收浏览器URL路径里面的某一个值,接收到的值会传给views.article_year(request,(\d{4})),那么在后端的代码里面article_year函数里面也要传2个参数。


# 在views.py里对应的配置。
def article_year(request,year):
    #数据库查询
    return HttpResponse(year)

 

5.2、URL的有名分组  —  根据定义的关键字传参 — 相当于关键字传参 — (?P<year>\d{4}) 只能接收数字

# 在urils.py里对应的配置。
from app01 import views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', views.article_year_month), 
    # year接收传入的第一个值并赋值给year(year=1999),month接收传入的第二个值并赋值给month(month=12)
]                                                       

# 在views.py里对应的配置。
def article_year_month(request,year,month):
    #数据库查询
    return HttpResponse(year+"/"+month)

 

5.3、URL的分发 —  每个应用下单独定义urls,只需要在项目目下做总的分发,实现解耦效果。

# 在项目目录下的urls.py文件内定义

from django.conf.urls import include, url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^app01/',include('app01.urls'))        # 定义访问app01应用的走app01目录下urls.py文件
]

# 那么在app01目录下urls.py文件定义如下:实现解耦的效果

from django.conf.urls import include, url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    # 无名分组
    url(r'^articles/(\d{4})/(\d{2})/$', views.article_year_month),
    # 有名分组
    url(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', views.article_year_month),
]

# 在views.py文件中的代码如下:
from django.shortcuts import render,HttpResponse

def article_year_month(request,year,month):
    return HttpResponse(year+":"+month)

# 访问的URL就必须加上app01前缀,否则无法访问
# http://127.0.0.1:8000/app01/articles/2005/19/

 

5.4、URL的反射  —  给固定的URL路径起一个别名,那么在使用路径时用这个别名即可。无论这个URL的路径在urls.py中如何修改,只要在前端html中定义”action={% url ‘login’ %}”,那么”{% url ‘login’ %}”就总能获取到urls.py中定义的URL路径(前端HTML不需要修改对应的路径)。–可参照 (7.2、渲染URL标签 {% %} )

在Html中写法:<form action="{% url 'login' %}" method="post">
在在Python中写法:url(r'^login/',views.login,name="login"),  # name="login" 定义一个别名叫"login"

# 例子:
# 在Python中:views.py文件中定义
urlpatterns = [
    url(r'^login/',views.login,name="login"),  

在 Html中:timer.html中定义
<form action="{% url 'login' %}" method="post"></form>  
  # 在html中,首先会查找有没有模板语法,如果没有的话,那么就直接丢给浏览器去读取html的内容了。
  # 如果有模板语法,那么根据模板语法的内容,去全局的urls.py文件中找一个叫"login"的别名字符串。
  # 找到"login"这个别名字符串后,会把这个别名对应的URL动态的获取,然后放在html中的action里面,然后交给浏览器去读取html中的action的内容。
]

 

例子:实现用户的登录及认证功能

# 前端HTML:
<body>

<form action="/login/" method="post">        {# login默认访问当前请求URL下的IP+端口/login/ #}  {# action: 用户提交后,请求到后端的地址 #}  {# method="post": 提交请求为"POST"请求 #}
    用户名: <input type="text" name="user">  {# 这个user是用来:获取用户输入的"用户名" #}
    密码: <input type="text" name="pwd">     {# 这个pwd是用来:获取用户输入的"密码" #}
    <input type="submit">                    {# submit是一次提交 #}
        
</form>

</body>

# 后端代码:
# 一、urls.py文件内

from app01 import views
urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^timer/', views.timer),

    # 二合一版本
    url(r'^login/', views.login),
]

# 二、views.py文件内

from django.shortcuts import render,HttpResponse
def login(request):
    method=request.method  # request.method 拿到的是用户请求一个页面的方式"GET"或者"POST"
    if method == "GET":    # 判断用户的请求方式
        return render(request,"login.html")  # 如果为"GET",则返回"login.html"
    else:
        user=request.POST.get("user")  # 通过“request.POST.get”,拿到前端用户输入的"用户名"
        pwd=request.POST.get("pwd")    # 通过“request.POST.get”,拿到前端用户输入的"密码"
        # 校验数据
        if user == "szq" and pwd == '123':
            return HttpResponse('登录成功')
        # 响应
        return HttpResponse("登录失败")

 

  六.视图语法  views.py

  6.1、request  — 请求信息

# 在views.py文件里面编辑:
# 然后访问:http://127.0.0.1:8000/index/ 拿到如下信息!

def index(request):
    # 请求信息
    print(request.GET)     # 发送GET请求
    # <QueryDict: {'a': ['1']}>

    print(request.POST)    # 发送POST请求
    # < QueryDict: {} >

    print(request.method)  # 获取本次请求的方式 "GET或POST"
    # GET

    print(request.path)    # 获取本次请求的相对路径
    # /index/

    print(request.get_full_path())    # 获取本次请求的全部路径(ip+port之后的路径地址)
    # /index/?a=1

 

  6.2、HttpResponse  —  响应信息

    1、Django必须响应HttpResponse对象

    2、HttpResponse 响应字符串

# 使用例子,在views.py文件中:
def index(request):
    return HttpResponse("首页!")

    3、render       响应模板(对应的html文件)

    4、redirect     重定向 — 用户登录成功后,重定向到网站首页!  (服务器让浏览器重定向请求,浏览器相当于请求了2次服务器)

# 使用例子,在views.py文件中:
def login(request):
    if request.method=="GET":
       return render(request,'login.html')
    else:
       if 1:
       return redirect("/index/")  # 在这里做了重定向跳转,跳转的路径为"/index/",触发这次重定向之后,就会跳转到http://127.0.0.1:8000/index/这个页面。

 

  七.模板语法  templates — 模板语法都是由render解析的  

   7.1、render方法的功能:
      方式一:return render(request,”login.html”)
           按着settings指定路径找到对应的login.html,读取文件内容,构建return HttpResponse(文件字符串)

      方式二:return render(request,”timer.html”,{“ctime”:ctime, “name”:name, “age”:age,})
           按着settings指定路径找到对应的timer.html,读取文件内容,进行渲染,把文件字符串中所有的{{}}的内容按着{“ctime”:ctime, “name”:name, “age”:age,}的方式进行替换,将新的替换字符串构建return HttpResponse(文件字符串)
 

   7.2、模板语法分为:

      1.变量 :1)深度查询,2)过滤器 

      2.标签

  1、模板语法之变量的用法 {{ }} 小例子:

# 渲染变量的
在Html中写法:<form action="{{ctime}}" method="post">
在在Python中写法:return render(request,"timer.html",{"ctime":ctime,"name":name,"age":age,})

# 例子:
# 在Python中:views.py文件中定义
def timer(request):
    import time
    ctime=str(time.time())
    name="sudada"
    age=18
    return render(request,"timer.html",{  # render能够找到"timer.html"文件,是因为在setting,py (里面的TEMPLATES定义了'DIRS': [os.path.join(BASE_DIR, 'templates'))。django会从全局变量里面找到templates目录]
                    "ctime":ctime,  #"ctime"是给templates里面的timer.html用的,而ctime取得是当前文件下的ctime
                    "name":name,    # 同"ctime"一样
                    "age":age,      # 同"ctime"一样
                })

在 Html中:timer.html中定义
<body>
<h3>当前时间: {{ ctime }}</h3>    # 调用后端里面的"ctime"
<h3>My name is: {{ name }}</h3>  # 同上
<h3>My age is: {{ age }}</h3>    # 同上
</body>

  2、模板语法之标签{% %}的用法 小例子:渲染URL标签 — 在Html模板里面对URL进行渲染  {% %}

# 渲染URL标签的
在Html中写法:<form action="{% url 'login' %}" method="post">
在在Python中写法:url(r'^login/',views.login,name="login"),  # name="login" 定义一个别名叫"login"

# 例子:
# 在Python中:views.py文件中定义
urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^login/',views.login,name="login"),  

在 Html中:timer.html中定义
<form action="{% url 'login' %}" method="post"></form>  
  # 在html中,首先会查找有没有模板语法,如果没有的话,那么就直接丢给浏览器去读取html的内容了。
  # 如果有模板语法,那么根据模板语法的内容,去全局的urls.py文件中找一个叫"login"的别名字符串。
  # 找到后会把这个别名动态的获取,然后放在html中,然后交给浏览器去读取html的内容。
]

 

 7.3、模板语法(变量)的使用:深度查询

  在python中的用法:

  如下:定义了”name” “l” “dic”等变量,以及类”Animal”等。

def template(request):
    '''
    模板语法:
        变量
            --- 深度查询
            --- 过滤器
    '''
    name="sudada"
    l=[11,22,33]
    dic={"name":"sudada","age":18,"sex":"male"}

    class Animal(object):
        def __init__(self,name,age):
            self.name=name
            self.age=age

    zzz=Animal("zzz",10)
    lll=Animal("lll",20)
    sss=Animal("sss",30)

    person_list=[zzz,lll,sss]

    return render(request,"templates.html",{"name":name,"l":l,"dic":dic,"person_list":person_list})
    # return render(request,"templates.html",locals())

  那么在前端是如何调用的呢?   前端HTML代码使用是效果展示:{{  }} 的方式调用Python里面定义的变量

<p>{{ name }}</p>
# sudada 拿到变量name的赋值

<<---------分隔----------->>

<p>{{ l }}</p>
#[11, 22, 33] 拿到l列表里面定义的所有值

<p>{{ l.0 }}</p>
#11 取l列表里面定义的第一个值

<p>{{ l.1 }}</p>
#22 取l列表里面定义的第二个值

<p>{{ l.2 }}</p>
#33 取l列表里面定义的第三个值

<<---------分隔----------->>

<p>{{ dic.name }}</p>
#sudada 取字典里面的第一个值

<p>{{ dic.age }}</p>
#18 取字典里面的第二个值
 
<p>{{ dic.sex }}</p>
#male 取字典里面的第三个值

<<---------分隔----------->>

<p>{{ person_list.0 }}</p>
#<app01.views.template.<locals>.Animal object at 0x000001AFD0655198> 拿到的是实例化的对象,可以看出定义的类为"Animal"

<p>{{ person_list.0.name }}</p>
#zzz 拿到的是列表person_list里面实例化后的对象name对应的值,0表示列表里面的第一个对象,name表示对象name对应的值。

<p>{{ person_list.0.age }}</p>
#10 同上

<p>{{ person_list.1.name }}</p>
#lll同上

<p>{{ person_list.1.age }}</p>
#20同上

<p>{{ zzz.name }}</p>
# zzz 直接获取对象zzz的name对应的值

<p>{{ zzz.age }}</p>
# 10 直接获取对象zzz的age对应的值

  7.4、模板语法(变量)的使用:过滤器语法 {{val(变量)|filter_name(过滤器名字):参数}}  — 更友好的显示一些数据

  在python中的用法:

def template(request):    
    """
    过滤器的使用之语法:{{val(变量)|filter_name(过滤器名字):参数}}
    """
    number=100
    import datetime
    now=datetime.datetime.now()

    # book_list=["三国演义","金瓶梅"]
    book_list=[]
    file_size=12312311
    s="Hello World"
    article="asd,哈哈哈,asd,爱 asd asd 12 lasdj lqniuqg id bsmnc buqho namv uqbwi namsb iuqoiejlqkwbdbnmasb j"

    link="<a href=''>rick</a>"
    # return render(request,"templates.html",{"name":name,"l":l,"dic":dic,"person_list":person_list}) # 写法一
    return render(request,"templates.html",locals())     # 写法二
    # locals() == {"name":name,"l":l,"dic":dic,"person_list":person_list}

  那么在前端是如何调用的呢?

  前端HTML代码使用是效果展示:

<h4>过滤器</h4>
<p>{{number|add:20}}</p>               
# number变量名,"|"固定写法,add表示加法,":"固定写法,20表示数字。表示在number=100的基础上在加20

<p>{{ now|date:"Y-m-d h:i" }}</p>      
# 原本"Dec. 30, 2018, 11:54 p.m."的格式加上过滤器date:"Y-m-d h:i"后,变成了"2018-12-30 11:54"

<p>{{ book_list|default:"没有符合条件的数据" }}</p>   
# 当book_list=[]为空的时候,默认显示"没有符合条件的数据",当book_list=["三国演义","金瓶梅"]里面存在值的时候,就显示列表里面的值。

<p>{{ file_size|filesizeformat }}</p>  
# 把file_size=123123123换算成字节大小,显示的效果为"117.4 MB"(格式单位自动调节),可以一眼看出文件有多大。

<p>{{ s|slice:"0:3" }}</p>             
# 对s="Hello World" 切片(顾头不顾尾),取"0:3"的值

<p>{{ s|slice:"0::2" }}</p>            
# 对s="Hello World" 切片(顾头不顾尾),每隔2个单位取一个值

{#展示一篇文章前面的一部分内容#}
<p>{{ article|truncatechars:10 }}</p>  
# 展示一片文章的前7个字符(后面会默认加...三个字符)
<p>{{ article|truncatewords:3 }}</p>   
# 展示一片文章的前3个单词(默认以空格为单词之间的分隔符分隔符)

<p>{{ link|safe }}</p>   
# Django的安全机制会将link="<a href=''>rick</a>"标签字符串进行转译,那么需要加上一个safe的过滤器,让他保持原意

 

7.4、自定义标签和过滤器

  1、在settings中的INSTALLED_APPS配置当前app01(项目名),不然django无法找到自定义的simple_tag.

  2、在app01中创建templatetags模块 (模块名只能是templatetags)

  3、创建任意 .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

@register.simple_tag 
def my_input(id,arg):          # 自定义标签函数
    result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
    return mark_safe(result)

4、在使用自定义simple_tag和filter的index.html文件中导入之前创建的 my_tags.py

# 在index.html文件中:
<body>

{% load my_tag %}

</body>

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

# 在index.html文件中:
<body>

{% load my_tag %}         # 导入自定义的过滤器
{{ 3|filter_multi:4 }}    # 3:表示第一个参数,4:表示第二个参数,这种方式只能传2个值。my_tags.py中的filter_multi函数会接受这2个值,并做下一步处理
{% my_input 'id_test' 'class_test' %}   # 给自定义标签my_input传值。

</body>

 

 7.5、模板语法(标签)的使用:for标签 {%%} -循环渲染

在Python里面的用法:

def template(request): 
    ###########标签############
    book_list = ["三国演义","金瓶梅","西游记"]
    dic={"name":"sudada",
         "age":18,
         "sex":"male",
         }
    return render(request,"templates.html",locals())

    #或者使用这种方式
    return render(request,"books.html",{"book_list":book_list})  

    # {"book_list":book_list} == locals()

  前端HTML代码使用是效果展示:

{% for n in book_list %}   # for 循环开始,针对列表循环
    <p>{{ n }}</p>
{% endfor %}               # for 循环结束,固定语法
三国演义
金瓶梅
西游记


{% for book in book_list %}
    <li>{{ book }}</li>
{% endfor %}
*三国演义
*金瓶梅
*西游记


{% for i in book_list %}
    <p>{{ forloop.counter }}  {{ i }}</p>
{% endfor %}
1 三国演义
2 金瓶梅
3 西游记


{% for key in dic %}     # 针对字典循环
    <p>{{ key }}</p>     # 拿到的值为字典的key
{% endfor %}
name
age
sex


{% for key,value in dic.items %}     # 针对字典里面的key和value的循环
    <p>{{ key }}  {{ value }}</p>
{% endfor %}
name sudada
age 18
sex male

 

 7.6、模板语法(标签)的使用:if标签-if条件判断

 在Python里面的用法:

def template(request): 
    ###########if 条件判断标签############
    score=90
    num_list=[123,34,546,8,98,2,344123,30,435457,65,456,4]

    return render(request,"templates.html",locals())

  前端HTML代码使用是效果展示:

<p>if 标签</p>

{% if score > 90 %}
<p>very good</p>
{% elif score > 60 %}
<p>good</p>
{% else %}
<p>NO</p>
{% endif %}
# 输出的值如下:
    good

<p>条件判断大于50的数字</p>  # for循环里面嵌套if条件判断

{% for num in num_list %}
{% if num > 50 %}
    <p>{{ num }}</p>
{% endif %}
{% endfor %}
# 输出的值如下:
    123
    546
    98
    344123
    435457
    65
    456

 

7.7、Django引入静态文件

  1、首先在项目根路径下创建 “static” 目录,然后把静态文件都放在这个目录下。

  2、在settings.py文件的最后一行,新增”static”目录

# 别名:之后在使用时,可以用别名代替实际路径
STATIC_URL = '/static/'   # 这个配置是Django自带就有的

# 文件的实际存在目录,给Django使用的
STATICFILES_DIRS=[
    os.path.join(BASE_DIR,"static")
]

  3、在前端html文件中引用静态文件

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>  # 引用免费CDN上面的js文件
    <script src='/static/jquery.js'></script>  # 引用static目录下的静态文件
</head>

 

7.8、Django模板的继承 

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

  1、继承的目的就是减少前端代码冗余

  2、Django模板继承大体就是:先写一个父类HTML,然后子类HTML继承父类HTML的代码的方式。 具体如下:

    2.1 父类HTML ,先写一堆父类HTML代码,然后定义一个 “block” (具体写法为:{% block Title %} )。“block”就是一个子类HTML可重写代码的部分。

{# 父类HTML文件base.html #}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
  
    {# 继承的写法#}
    {% block Title %}
        <title>Title</title>
    {% endblock %}

    <meta name="viewport" content="width=device-width,initial-scale=1">
    {# 使用这套布局方式 #}
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .header{    {# 设置页面头部格式 #}
            width: 100%;
            height: 60px;
            background-color: #369;
        }
    </style>

</head>
<body>

<div class="header"></div>

<div class="container">
    <div class="row">

        <div class="col-md-3">
            <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>
        <div class="col-md-9">
            {% block centent %}   {# block的功能:当其他的html文件继承base.html(当前文件)时,可以重写centent的内容。 #}  {# centent这个名字不是固定写法 #}
                <p>这是一个盒子</p>
            {% endblock %}

        </div>

    </div>
</div>


</body>
</html>

    2.2 子类HTML ,继承父类HTML的方法 (只能继承一个父类HTML模板)

       1). 在子类HTML中,使用{% extends “base.html” %} 明确继承哪个父类HTML

       2). 在子类HTML中,使用{% block centent %} 自定义代码

{# 子类HTML文件order.html #}
{% extends "base.html" %}    {# 继承base.html文件,必须放在第一位 #}

{% block centent %}     {# 然后重写block里面的内容 #}
    <h3>订单列表</h3>
        {% for order in order_list %}
            <p>{{ order }}</p>
        {% endfor %}
{% endblock %}

 

  3、在子类HTML中使用{% block centent %}重写HTML后,还想要显示父类HTML中的{% block centent %},这种需要该如何实现。

{% extends "base.html" %}

{% block centent %}
    <h3>商品列表</h3>
        {% for shopper in shopper_list %}
            <p>{{ shopper }}</p>
        {% endfor %}

        <div>{{ block.super }}</div>   {# 写一个div标签,然后加上"{{ block.super }}"就可以了 #}

{% endblock %}

 

  4、使用继承的一些注意事项

1).如果你在模版中使用 {% extends %} 标签,它必须是模版中的第一个标签。其他的任何情况下,模版继承都将无法工作。

2).在base模版中设置越多的 {% block %} 标签越好。请记住,子模版不必定义全部父模版中的blocks,所以,你可以在大多数blocks中填充合理的默认内容,然后,只定义你需要的那一个。多一点钩子总比少一点好。

3).如果你发现你自己在大量的模版中复制内容,那可能意味着你应该把内容移动到父模版中的一个 {% block %} 中。

4).为了更好的可读性,你也可以给你的 {% endblock %} 标签一个 名字 。例如:
          {% block content %}
          ...
         {% endblock content %}  

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

6).最后,请注意您并不能在一个模版中定义多个相同名字的 block 标签。这个限制的存在是因为block标签的作用是“双向”的。这个意思是,block标签不仅提供了一个坑去填,它还在 _父模版_中定义了填坑的内容。如果在一个模版中有两个名字一样的 block 标签,模版的父模版将不知道使用哪个block的内容。

 

转载自:https://blog.csdn.net/sinat_29214327/article/details/85226171

You may also like...