GVKun编程网logo

Django模板系统-母板和继承(django母版)

12

如果您对Django模板系统-母板和继承感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于Django模板系统-母板和继承的详细内容,我们还将为您解答django母版的相关问题

如果您对Django模板系统-母板和继承感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于Django模板系统-母板和继承的详细内容,我们还将为您解答django母版的相关问题,并且为您提供关于01 - Django模板系统、19 Django模板自定义标签和过滤器,模板继承 (extend),Django的模型层-ORM简介、Django 2.0 学习(13):Django模板继承和静态文件、Django 之 模板系统的有价值信息。

本文目录一览:

Django模板系统-母板和继承(django母版)

Django模板系统-母板和继承(django母版)

母板和继承

母版

  1. html页面,提取多个页面的公共部分

  2. 定义多个block块,需要让子页面进行填充

<head>
   {% block page-css %}
   
  {% endblock %}
</head>
<body>
​
<h1>这是母板的标题</h1>
​
{% block page-main %} # 设置block块,可以在模板中进行个性化设置
{% endblock %}
​
<h1>母板底部内容</h1>
{% block page-js %}
​
{% endblock %}
</body>

继承

  1. 在模板的左上方写上{% extends ''母板文件名'' %}

  2. 重写block块 ,写在block内部

  3. 块block

    {% extends ''home.html''%}
     {% block page-main %}
      <p>《叽叽喳喳的世界》</p>
      <p>作者:叽叽喳喳</p>
     {% endblock %}  

注意

  1. {% extends ''base.html'' %} 带上引号 不带的话会当做变量

  2. {% extends ''base.html'' %} 上面不要写其他内容

  3. 要显示的内容写在block块中

  4. 母板定义多个block 用于定义 css 或者 js

组件

可以将常用的页面内容如导航条,页尾信息等不会已经写完不会经常更改的组件保存在单独的文件中,然后在需要使用的地方按如下语法导入即可。

{% include ''组件模板'' %}

静态文件相关

静态文件引入
引用CSS
 {% load static %}
 <link rel="stylesheet" href="{% static ''css/dashboard.css'' %}">
 ​
 引用JS
 {% load static %}
 <script src="{% static "mytest.js" %}"></script>
 ​
 引用图片
 {% load static %}
 <img src="{% static "images/hi.jpg" %}" alt="Hi!" />
 ​
 某个文件多处被用到可以存为一个变量
 {% load static %}
 {% static "images/hi.jpg" as myphoto %}
 <img src="{{ myphoto }}"></img>
使用get_static_prefix
# 方式一
 {% load static %}
 <img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />
 ​
 # 方式二
 {% load static %}
 {% get_static_prefix as STATIC_PREFIX %}
 ​
 <img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" />
 <img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />
自定义simpletag

和自定义filter类似,只不过接收更灵活的参数。

定义注册simple_tag

@register.simple_tag(name="plus")  # 可以省略(name="plus")
 def plus(a, b, c):
    return f"{a} + {b} + {c}"

使用自定义simple_tag

{% load tag %}  #(load 文件名)即可
 ​
 {% plus "1" "2" "abc" %}

【与filter的区别】

  • filter是过滤器,simple_tag是标签

  • filter最多传入两个参数

inclusion_tag

多用于返回html代码片段

templatetags/my_inclusion.py设计功能

from django import template
 ​
 register = template.Library()
 ​
 @register.inclusion_tag(''page.html'')  # 结合的是page.html模板
 def page(num):
    return {''num'':range(1,num+1)}   # 返回必须是一个字典

templates/page.html进行组件设计

# page模板中存放的是一个分页组件
 ​
 <nav aria-label="Page navigation">
  <ul>
    <li>
      <a href="#" aria-label="Previous">
        <span aria-hidden="true">«</span>
      </a>
    </li>
     
    {% for i in num %}
          <li>
              <a href="#">{{ i }}</a>
          </li>
      {% endfor %}
 ​
    <li>
      <a href="#" aria-label="Next">
        <span aria-hidden="true">»</span>
      </a>
    </li>
  </ul>
 </nav>

templates/jjzz.html中进行调用

<body>
 ​
 {% load my_inclusion %}
 {% page 5 %}
 ​
 </body>
 </html>

01 - Django模板系统

01 - Django模板系统

Django模板:

  官方文档

常用语法:

1 {{ }}表示变量,在模板渲染的时候替换成值,{% %}表示逻辑相关的操作,{#....#}代表注释
2 {# 取l中的第一个参数 #}
3 {{ l.0 }}
4 {# 取字典中key的值 #}
5 {{ d.name }}
6 {# 取对象的name属性 #}
7 {{ person_list.0.name }}
8 {# .操作只能调用不带参数的方法 #}
9 {{ person_list.0.dream }}

注:当模板系统遇到一个(.)时,会按照如下的顺序去查询:

  1. 在字典中查询
  2. 属性或者方法
  3. 数字索引

Filters

用来修改变量的显示结果。

语法: {{ value|filter_name:参数 }}

''|''左右没有空格没有空格没有空格

1 #flter支持链式操作
2 #例如:
3 {{ value|first|upper}}     #首字母大写

 

1、默认值

1 default
2 {{ value|default:"nothing"}}    #如果value值没传的话就显示nothing

2、格式化值

1 1 default
2 2 {{ value|default:"nothing"}}    #如果value值没传的话就显示nothing

3、相加

1 add
2 #给变量加参数
3 {{ value|add:"2" }}    #value是数字4,则输出结果为6。
4 {{ first|add:second }} #如果first是 [1,.2,3] ,second是 [4,5,6] ,那输出结果是 [1,2,3,4,5,6] 。

4、大小写

lower
#小写
{{ value|lower }}

upper
#大写
{{ value|upper}}

5、对齐方式

ljust
 #左对齐
 {{ value|ljust:"10" }}
 rjust
 
 #右对齐
 {{ value|rjust:"10" }}
 
 center
 #居中
 {{ value|center:"15" }}

5、标题

1 #标题
2 {{ value|title }}

6、返回value的长度

1 {{ value|length }}
2 #返回value的长度,如 value=[''a'', ''b'', ''c'', ''d'']的话,就显示4.

7、切片

 1 slice  
 2 #切片
 3 {{value|slice:"2:-1"}}
 4 
 5 first
 6 #取第一个元素
 7 {{ value|first }}
 8 
 9 last
10 #取最后一个元素
11 {{ value|last }}

8、字符串拼接

1 #使用字符串拼接列表。同python的str.join(list)。
2 {{ value|join:" // " }}

 

9、字符截取

1 truncatechars
2 #如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
3 #参数:截断的字符数
4 {{ value|truncatechars:9}}

 

10、日期格式化:

1 date
2 #日期格式化
3 {{ value|date:"Y-m-d H:i:s"}}

 

11、不必转义

safe
#Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。

比如:

value = "<a href=''#''>点我</a>"

{{ value|safe}}

 

 

自定义filter

自定义过滤器只是带有一个或两个参数的Python函数:

  • 变量(输入)的值 - -不一定是一个字符串
  • 参数的值 - 这可以有一个默认值,或完全省略

例如,在过滤器{{var | foo:“bar”}}中,过滤器foo将传递变量var和参数“bar”

自定义filter代码文件摆放位置:

1 app01/
2     __init__.py
3     models.py
4     templatetags/  # 在app01下面新建一个package package
5         __init__.py
6         app01_filters.py  # 建一个存放自定义filter的py文件
7     views.py

 

编写自定义的filter

 1 from django import template
 2 register = template.Library()
 3 
 4 
 5 @register.filter
 6 def fill(value, arg):
 7     return value.replace(" ", arg)
 8 
 9 
10 @register.filter(name="addSB")
11 def add_sb(value):
12     return "{} SB".format(value)

使用自定义的filter

1 {# 先导入我们自定义filter那个文件 #}
2 {% load app01_filters %}
3 
4 {# 使用我们自定义的filter #}
5 {{ somevariable|fill:"__" }}
6 {{ d.name|addSB }}

 Tags

1、for循环

1 <ul>
2 {% for user in user_list %}
3     <li>{{ user.name }}</li>
4 {% empty %}
5     <li>空空如也</li>
6 {% endfor %}
7 </ul>

 

for循环使用的一些参数:

Variable Description
forloop.counter 当前循环的索引值(从1开始)
forloop.counter0 当前循环的索引值(从0开始)
forloop.revcounter 当前循环的倒序索引值(从1开始)
forloop.revcounter0 当前循环的倒序索引值(从0开始)
forloop.first 当前循环是不是第一次循环(布尔值)
forloop.last 当前循环是不是最后一次循环(布尔值)
forloop.parentloop 本层循环的外层循环

 2、if,elif和else

1 #if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。
2 {% if user_list %} 3 用户人数:{{ user_list|length }} 4 {% elif black_list %} 5 黑名单数:{{ black_list|length }} 6 {% else %} 7 没有用户 8 {% endif %}

3、with:

定义一个中间变量,如果觉得自己的变量名太长,可以用with赋一个别名
1 {% with total=business.employees.count %}
2     {{ total }} employee{{ total|pluralize }}
3 {% endwith %}

 

 4、csrf_token

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

在页面的form表单里面写上{% csrf_token %}

5、注意事项

 1 1. Django的模板语言不支持连续判断,即不支持以下写法:
 2 
 3 {% if a > b > c %}
 4 ...
 5 {% endif %}
 6 2. Django的模板语言中属性的优先级大于方法
 7 
 8 def xx(request):
 9     d = {"a": 1, "b": 2, "c": 3, "items": "100"}
10     return render(request, "xx.html", {"data": d})
11 如上,我们在使用render方法渲染一个页面的时候,传的字典d有一个key是items并且还有默认的 d.items() 方法,此时在模板语言中:
12 
13 {{ data.items }}
14 默认会取d的items key的值。
 1 1. Django的模板语言不支持连续判断,即不支持以下写法:
 2 
 3 {% if a > b > c %}
 4 ...
 5 {% endif %}

6 2. Django的模板语言中属性的优先级大于方法 7 8 def xx(request): 9 d = {"a": 1, "b": 2, "c": 3, "items": "100"} 10 return render(request, "xx.html", {"data": d}) 11 如上,我们在使用render方法渲染一个页面的时候,传的字典d有一个key是items并且还有默认的 d.items() 方法,此时在模板语言中: 12 13 {{ data.items }} 14 默认会取d的items key的值。

 

自定义simpletag

和自定义filter类似,只不过接收更灵活的参数。

1、定义注册simple tag
1 @register.simple_tag(name="plus")
2 def plus(a, b, c):
3     return "{} + {} + {}".format(a, b, c)

2、使用自定义simple tag

{% load app01_demo %}

{# simple tag #}
{% plus "1" "2" "abc" %}

inclusion_tag:

类似于自定义的sim;pletag,不过inclusion_tag多用于返回html代码片段

templatetags/my_inclusion.py

 1 from django import template
 2 
 3 register = template.Library()
 4 
 5 
 6 @register.inclusion_tag(''result.html'')
 7 def show_results(n):
 8     n = 1 if n < 1 else int(n)
 9     data = ["第{}项".format(i) for i in range(1, n+1)]
10     return {"data": data}

templates/result.html

1 <ul>
2   {% for choice in data %}
3     <li>{{ choice }}</li>
4   {% endfor %}
5 </ul>

templates/index.html

<!DOCTYPE html>
<html lang="en">
<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>inclusion_tag test</title>
</head>
<body>

{% load my_inclusion %}

{% show_results 10 %}
</body>
</html>

 

母版

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4   <meta charset="UTF-8">
 5   <meta http-equiv="x-ua-compatible" content="IE=edge">
 6   <meta name="viewport" content="width=device-width, initial-scale=1">
 7   <title>Title</title>
 8   {% block page-css %}
 9   
10   {% endblock %}
11 </head>
12 <body>
13 
14 <h1>这是母板的标题</h1>
15 
16 {% block page-main %}
17 
18 {% endblock %}
19 <h1>母板底部内容</h1>
20 {% block page-js %}
21 
22 {% endblock %}
23 </body>
24 </html>

 

继承母版

1 在子页面中在页面最上方使用下面的语法来继承母板。
2 {% extends ''layouts.html'' %}

 

通过在母板中使用{% block  xxx %}来定义"块"。

在子页面中通过定义母板中的block名来对应替换母板中相应的内容。

1 {% block page-main %}
2   <p>世情薄</p>
3   <p>人情恶</p>
4   <p>雨送黄昏花易落</p>
5 {% endblock %}

组件

可以将常用的页面内容如导航条,页尾信息等组件保存在单独的文件中,然后在需要使用的地方按如下语法导入即可。

1 {% include ''navbar.html'' %}

 

静态文件相关

1 {% load static %}
2 <img src="{% static "images/hi.jpg" %}" alt="Hi!" />

引用JS文件时使用:

1 {% load static %}
2 <script src="{% static "mytest.js" %}"></script>

 

某个文件多处被用到可以存为一个变量

1 {% load static %}
2 {% static "images/hi.jpg" as myphoto %}
3 <img src="{{ myphoto }}"></img>

使用get_static_prefix

1 {% load static %}
2 <img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />

 

或者

1 {% load static %}
2 {% get_static_prefix as STATIC_PREFIX %}
3 
4 <img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" />
5 <img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />

 

19 Django模板自定义标签和过滤器,模板继承 (extend),Django的模型层-ORM简介

19 Django模板自定义标签和过滤器,模板继承 (extend),Django的模型层-ORM简介

一、模板自定义标签和过滤器

标签,是为了做一些功能。过滤器,是对斜杠前面的数据做过滤。

为什么要自定义标签和过滤器?因为自带的不够用,需要结合需求,来自定义。

自定义标签和过滤器需要执行3个步骤:

1、在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.

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

3、创建任意 .py 文件,如:my_tags.py

自定义过滤器

举例:增加一个乘法过滤器

修改settings.py中的INSTALLED_APPS,最后一行添加当前的app。

django开头的,都是一些自带的app。它内置在django源码里面!

INSTALLED_APPS = [
    ''django.contrib.admin'',
    ''django.contrib.auth'',
    ''django.contrib.contenttypes'',
    ''django.contrib.sessions'',
    ''django.contrib.messages'',
    ''django.contrib.staticfiles'',
    ''app01.apps.App01Config'',
]
View Code

在app01目录里面新建一个templatetags目录,目录名必须是这个!!!否则django找不到。

目录里面创建my_filter_tag.py,这个py文件名,可以随便定义。内容如下:

from django import template
from django.utils.safestring import mark_safe
register=template.Library()

@register.filter
def multi_filter(x,y):
    return x*y
View Code

注意:头部的3行,是固定写法,不能改变。

增加@register.filter,是为了将函数转换成过滤器。函数的名字,可以自定义。

修改views.py里面的index函数,内容如下:

def index(request):
    num = 100
    return render(request,''index.html'',{''num'':num})
View Code

修改index.html,修改body部分

注意:在使用自定义标签和过滤器,必须在html文件中,导入之前创建的my_filter_tag

{% load my_filter_tag %}
<p>{{ num|multi_filter:5 }}</p>
View Code

load表示导入模块。p标签中的内容,是执行了multi_filter过滤器。

注意:它接收了2个参数。一个是num,一个是5。因为multi_filter过滤器,定义了2个形参,使用它必须传2个参数才行。

访问index页面,输出:

是因为自定义的模块,没有导入成功,提示找不到!为啥呢?因为django项目启动时,会导入settings.py定义的模块导入,由于app01的自定义模块是启动之后加的,所以它并没有加载进去。

重启django项目,就可以加载了。

再次访问index,页面输出:

 

 如果要完成3位乘法呢?过滤器可以增加一个形参,但是index.html怎么加第3个参数呢?

答案是,它不能加第3个参数。所以只能在后端,将参数形式修改列表,元组,字典等方式,就可以了。

举例1:计算4*5*6

修改index视图函数

def index(request):
    num1 = 4
    num2 = 5
    num3 = 6
    num_list = [num1,num2,num3]
    return render(request,''index.html'',{''num_list'':num_list})
View Code

修改my_filter_tag.py中的过滤器

@register.filter
def multi_filter(num_list):
    res = 1
    for i in num_list:
        res*=i
    return res
View Code

修改index.html,修改body部分

{% load my_filter_tag %}
<p>{{ num_list|multi_filter }}</p>
View Code

访问网页,输出:

 

举例1:显示a标签

修改my_filter_tag.py文件,增加link_tag过滤器

@register.filter
def link_tag(href):
    return "<a href=%s>click</a>"%href
View Code

修改index视图函数

def index(request):
    link = "http://www.py3study.com/"
    return render(request,''index.html'',{''link'':link})
View Code

修改index.html,修改body部分

{% load my_filter_tag %}
<p>{{ link|link_tag }}</p>
View Code

访问网页,输出:

发现结果不是我们想要的,查看浏览器控制台,查看响应体,发现被转义了

因为django遇到html或者js标签,会转义。它认为是不安全的!那么如何告诉它,是安全的呢?

需要在过滤器中导入make_safe模块

修改my_filter_tag.py文件中的link_tag过滤器,完整代码如下:

使用make_safe方法,告诉django是安全的,不需要转义

from django import template
from django.utils.safestring import mark_safe
register=template.Library()

@register.filter
def multi_filter(num_list):
    res = 1
    for i in num_list:
        res*=i
    return res

@register.filter
def link_tag(href):
    return mark_safe("<a href=%s>click</a>" % href)
View Code

重启django项目,因为网页有缓存,懒得清理了,所以直接重启django项目,见效快! 

再次访问

效果就出来了。

 

自定义标签

标签,是为了做一些功能

举例:4个参数的乘法运算

修改my_filter_tag.py,增加multi_tag函数

@register.simple_tag
def multi_tag(x,y,z):
    return x*y*z
View Code

@register.simple_tag表示将函数转换为自定义标签

 

修改index.html,修改body部分

注意:调用标签,使用{% 标签过滤器名 参数1,参数2,参数3... %}

参数不限,但不能放在if for语句中

{% load my_filter_tag %}
<p>{% multi_tag 7 8 9 %}</p>
View Code

重启django项目,访问网页,输出:

 

自定义标签和自定义过滤器的区别:

1. 标签,是为了做一些功能。过滤器,是对斜杠前面的数据做过滤。

2. 标签可以写任意个形参,而过滤器最大只能写2个形参。如果过滤器需要接收多个参数,需要将参数存放在列表,元组,字典等数据中。

3. 过滤器可以用在if等语句后,标签不可以

 

二、模板继承 (extend)

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

通过从下面的例子开始,可以容易的理解模版继承:

include

新建advertise.html,使用Bootstrap构建2个面板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>

<div class="row">
    <div class="col-md-4">
        <div class="advertise">
            <div class="panel panel-danger">
                <div class="panel-heading">菜单一</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-success">
                <div class="panel-heading">菜单一</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
        </div>

    </div>
</div>

</body>
</html>
View Code

修改urls.py,增加advertise路径

urlpatterns = [
    path(''admin/'', admin.site.urls),
    path(''index/'', views.index),
    path(''advertise/'', views.advertise),
]
View Code

修改views.py,增加advertise视图函数

def advertise(request):
    return render(request, ''advertise.html'')
View Code

访问url: http://127.0.0.1:8000/advertise/

如果首页,也想显示左边的菜单栏呢?代码复制一遍?

这样代码就重复了,使用include,就可以了。

修改advertise.html,将相同的部分分离处理

<div class="row">
    <div class="col-md-4">
        <div class="advertise">
            <div class="panel panel-danger">
                <div class="panel-heading">菜单一</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-success">
                <div class="panel-heading">菜单一</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
        </div>

    </div>
</div>
View Code

修改index.html,使用include导入advertise.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
{% include ''advertise.html'' %}
</body>
</html>
View Code

访问首页,效果同上。

 

 extend

 访问博客园的个人博客,发现很多页面,有几处相同的部分。比如右侧的侧边栏,顶部的导航栏,尾部部分...等等。

那么公共区域,不需要自己重复写,继承下来就可以了!

举例:图书网页

编辑index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .header {
            width: 100%;
            height: 60px;
            background-color: #369;
        }

        .title {

            line-height: 60px;
            color: white;
            font-weight: 100;
            margin-left: 20px;
            font-size: 20px;
        }
        .container{
            margin-top: 20px;
        }
    </style>
</head>
<body>
<div class="header">
    <p class="title">
        路飞学诚
    </p>
</div>
<div class="container">
    <div class="row">
        <div class="col-md-3">
            <div class="panel panel-danger">
                <div class="panel-heading">菜单一</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-success">
                <div class="panel-heading">菜单二</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-warning">
                <div class="panel-heading">菜单三</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
        </div>
        <div class="col-md-9">
           <div class="jumbotron">
                <h1>Hello, INDEX!</h1>
                <p>...</p>
                <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
            </div>
        </div>
    </div>
</div>
</body>
</html>
View Code

访问index页面,输出:

urlpatterns = [
    path(''admin/'', admin.site.urls),
    path(''index/'',views.index),
    path(''articles/'',views.articles),
    path(''authors/'',views.authors),
]
View Code

修改views.py,增加2个视图函数

def articles(request):
    return render(request, ''articles.html'')

def authors(request):
    return render(request, ''authors.html'')
View Code

新建articles.html,将index.html的代码全部复制粘贴过来,修改中间内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .header {
            width: 100%;
            height: 60px;
            background-color: #369;
        }

        .title {

            line-height: 60px;
            color: white;
            font-weight: 100;
            margin-left: 20px;
            font-size: 20px;
        }
        .container{
            margin-top: 20px;
        }
    </style>
</head>
<body>
<div class="header">
    <p class="title">
        路飞学诚
    </p>
</div>
<div class="container">
    <div class="row">
        <div class="col-md-3">
            <div class="panel panel-danger">
                <div class="panel-heading">菜单一</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-success">
                <div class="panel-heading">菜单二</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-warning">
                <div class="panel-heading">菜单三</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
        </div>
        <div class="col-md-9">
            <div class="article_list">
               <ul>
                   <li>红楼梦</li>
                   <li>三国演义</li>
                   <li>西游记</li>
                   <li>水浒传</li>
               </ul>
           </div>
        </div>
    </div>
</div>
</body>
</html>
View Code

访问articles页面,效果如下:

 

新建authors.html,将index.html的代码全部复制粘贴过来,修改中间内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .header {
            width: 100%;
            height: 60px;
            background-color: #369;
        }

        .title {

            line-height: 60px;
            color: white;
            font-weight: 100;
            margin-left: 20px;
            font-size: 20px;
        }
        .container{
            margin-top: 20px;
        }
    </style>
</head>
<body>
<div class="header">
    <p class="title">
        路飞学诚
    </p>
</div>
<div class="container">
    <div class="row">
        <div class="col-md-3">
            <div class="panel panel-danger">
                <div class="panel-heading">菜单一</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-success">
                <div class="panel-heading">菜单二</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-warning">
                <div class="panel-heading">菜单三</div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
        </div>
        <div class="col-md-9">
            <div class="author_list">
               <ul>
                   <li>曹雪芹</li>
                   <li>罗贯中</li>
                   <li>吴承恩</li>
                   <li>施耐庵</li>
               </ul>
           </div>
        </div>
    </div>
</div>
</body>
</html>
View Code

访问authors页面,效果如下:

 

 

问题来了,菜单和导航,都是重复的。有了继承,就可以解决这个问题。
公共部分有,继承的子页面就会有。没有的部分,子页面也不会有。

 

这个模版,我们把它叫作 base.html, 它定义了一个可以用于两列排版页面的简单HTML骨架。“子模版”的工作是用它们的内容填充空的blocks。

在这个例子中, block 标签定义了三个可以被子模版内容填充的block。 block 告诉模版引擎: 子模版可能会覆盖掉模版中的这些位置。

子模版可能看起来是这样的:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
     <title>title</title>
    <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 {
            width: 100%;
            height: 60px;
            background-color: #369;
        }

        .title {

            line-height: 60px;
            color: white;
            font-weight: 100;
            margin-left: 20px;
            font-size: 20px;
        }
        .container{
            margin-top: 20px;
        }
    </style>
</head>
<body>

<div class="header">
    <p class="title">
        路飞学诚
    </p>
</div>

<div class="container">
    <div class="row">
        <div class="col-md-3">
            <div class="panel panel-danger">
                <div class="panel-heading"><a href="http://127.0.0.1:8008/index/">首页</a></div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-success">
                <div class="panel-heading"><a href="http://127.0.0.1:8008/authors/">作者</a></div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-warning">
                <div class="panel-heading"><a href="http://127.0.0.1:8008/articles/">文章管理</a></div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
        </div>
        <div class="col-md-9">
           {% block content %}

           {% endblock %}
        </div>
    </div>
</div>

</body>
</html>
View Code

修改index.html,删除多余的代码。继承base.html

它是先继承,再填充内容。

extends 标签是这里的关键。它告诉模版引擎,这个模版“继承”了另一个模版。当模版系统处理这个模版时,首先,它将定位父模版——在此例中,就是“base.html”。

那时,模版引擎将注意到 base.html 中的三个 block 标签,并用子模版中的内容来替换这些block。根据 blog_entries 的值,输出可能看起来是这样的:

{% extends ''base.html'' %}

{% block content %}
<div class="jumbotron">
    <h1>Hello, INDEX!</h1>
    <p>...</p>
    <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
</div>
{% endblock %}
View Code

访问index页面,效果如下:

 

修改articles.html,继承base.html

{% extends ''base.html'' %}

{% block content %}
<div class="article_list">
   <ul>
       <li>红楼梦</li>
       <li>三国演义</li>
       <li>西游记</li>
       <li>水浒传</li>
   </ul>
</div>
{% endblock %}
View Code

访问articles页面,效果如下:

修改authors.html,继承base.html

{% extends ''base.html'' %}

{% block content %}
<div class="author_list">
    <ul>
       <li>曹雪芹</li>
       <li>罗贯中</li>
       <li>吴承恩</li>
       <li>施耐庵</li>
    </ul>
</div>
{% endblock %}
View Code

访问authors页面,效果如下:

 

这样,就解决了代码重复问题

 

需求,访问不同页面时,更改tile标签的属性

怎么做呢?很简单,在base.html里面的title标签位置,定义一个block

在花括号中间的title标签,表示默认值。如果子页面不设置block title,那么显示默认值。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    {% block title %}
     <title>title</title>
    {% endblock title %}
    
    <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 {
            width: 100%;
            height: 60px;
            background-color: #369;
        }

        .title {

            line-height: 60px;
            color: white;
            font-weight: 100;
            margin-left: 20px;
            font-size: 20px;
        }
        .container{
            margin-top: 20px;
        }
    </style>
</head>
<body>

<div class="header">
    <p class="title">
        路飞学诚
    </p>
</div>

<div class="container">
    <div class="row">
        <div class="col-md-3">
            <div class="panel panel-danger">
                <div class="panel-heading"><a href="http://127.0.0.1:8008/index/">首页</a></div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-success">
                <div class="panel-heading"><a href="http://127.0.0.1:8008/authors/">作者</a></div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-warning">
                <div class="panel-heading"><a href="http://127.0.0.1:8008/articles/">文章管理</a></div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
        </div>
        <div class="col-md-9">
           {% block content %}

           {% endblock %}
        </div>
    </div>
</div>

</body>
</html>
View Code

修改articles.html,增加一个block

{% extends ''base.html'' %}

{% block content %}
 {{ block.super }}
 <div class="article_list">
   <ul>
       <li>红楼梦</li>
       <li>三国演义</li>
       <li>西游记</li>
       <li>水浒传</li>
   </ul>
</div>
{% endblock %}

{% block title %}
<title>Article</title>
{% endblock %}
View Code

访问articles页面,标题就出来了,效果如下:

访问authors页面,标题就出来了,效果如下:

由于没有设置block title,它显示默认值。

 

现在有一个问题,右侧内容,写死了。比如文章页中的内容
修改views.py,2个视图,分别增加一个列表

def articles(request):
    acticle_list = [''红楼梦'',''三国演义'',''西游记'',''水浒传'']
    return render(request, ''articles.html'',{''acticle_list'':acticle_list})

def authors(request):
    author_list = [''曹雪芹'',''罗贯中'',''吴承恩'',''施耐庵'']
    return render(request, ''authors.html'',{''author_list'':author_list})
View Code

修改修改articles.html,增加一个for循环

{% extends ''base.html'' %}

{% block content %}
 <div class="article_list">
   <ul>
       {% for article in acticle_list %}
       <li>{{ article }}</li>
       {% endfor %}
   </ul>
</div>
{% endblock %}

{% block title %}
<title>Article</title>
{% endblock %}
View Code

修改修改authors.html,增加一个for循环

{% extends ''base.html'' %}

{% block content %}
<div class="author_list">
    <ul>
       {% for author in author_list %}
       <li>{{ author }}</li>
       {% endfor %}
    </ul>
</div>
{% endblock %}

{% block title %}
<title>Author</title>
{% endblock %}
View Code

重新访问2个页面,效果同上。

 

请注意,子模版并没有定义 sidebar block,所以系统使用了父模版中的值。父模版的 {% block %} 标签中的内容总是被用作备选内容(fallback)。

这种方式使代码得到最大程度的复用,并且使得添加内容到共享的内容区域更加简单,例如,部分范围内的导航。

这里是使用继承的一些提示:

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

举例:下面这种写法是错误的。extends必须在block上面才行。

{% block content %}
<div class="jumbotron">
    <h1>Hello, INDEX!</h1>
    <p>...</p>
    <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
</div>
{% endblock %}

{% extends ''base.html'' %}
View Code

 访问网页,就会报错

 

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

比如:base.html虽然定义了2个blocks,authors页面可以只继承一个。

 

  • 如果你发现你自己在大量的模版中复制内容,那可能意味着你应该把内容移动到父模版中的一个 {% 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.

翻译:

如果您需要从父模板获取块的内容,则{{block.super}}变量将执行该操作。如果你想添加父块的内容而不是完全覆盖父块的内容,这很有用。使用{{block.super}}插入的数据不会自动转义(请参阅下一节),因为它已经在父模板中被转义(如有必要)。

举例:

在base.html中block content里面增加一个h3标签。既系统子页面显示h3标签,同时子标签填充block content里面的内容时,h3标签不会被覆盖。加入一个{{block.super}}就可以了。

修改base.html,加入h3标签。修改block content部分

{% block content %}
<h3>详细内容</h3>
{% endblock %}

修改articles.html,在block content 下面一行,增加{{block.super}}

{% extends ''base.html'' %}

{% block content %}
{{ block.super }}
 <div class="article_list">
   <ul>
       {% for article in acticle_list %}
       <li>{{ article }}</li>
       {% endfor %}
   </ul>
</div>
{% endblock %}

{% block title %}
<title>Article</title>
{% endblock %}
View Code

访问articles页面,效果如下

注意:如果子页面没有写{{block.super}},那么h3标签就会被覆盖!

 

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

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

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

比如base.html中的block title,就是遵循这种写法。

  • 不能在一个模版中定义多个相同名字的 block 标签,否则会被覆盖

 

需求:现在的页面是手动跳转的,需要点击菜单时,自动跳转页面。

修改base.html,增加3个a标签。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    {% block title %}
     <title>title</title>
    {% endblock title %}

    <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 {
            width: 100%;
            height: 60px;
            background-color: #369;
        }

        .title {

            line-height: 60px;
            color: white;
            font-weight: 100;
            margin-left: 20px;
            font-size: 20px;
        }
        .container{
            margin-top: 20px;
        }
    </style>
</head>
<body>

<div class="header">
    <p class="title">
        路飞学诚
    </p>
</div>

<div class="container">
    <div class="row">
        <div class="col-md-3">
            <div class="panel panel-danger">
                <div class="panel-heading"><a href="/index/">首页</a></div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-success">
                <div class="panel-heading"><a href="/authors/">作者</a></div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
            <div class="panel panel-warning">
                <div class="panel-heading"><a href="/articles/">文章管理</a></div>
                <div class="panel-body">
                    Panel content
                </div>
            </div>
        </div>
        <div class="col-md-9">
           {% block content %}
            <h3>详细内容</h3>
           {% endblock %}
        </div>
    </div>
</div>

</body>
</html>
View Code

访问网页,点击左边的连接,就可以任意跳转了。

效果如下:

 

 

三、Django的模型层-ORM简介

ORM简介

ORM,全称是object relation mapping。翻译过来,就是对象关系映射。

主要来学习MySQL操作,MySQL是一个软件。它的优点:1.免费 2.开源

pymysql,就是Mysql给Python提供的接口。早期的接口叫mysqldb

ORM可以实现不写sql语句,就可以实现操作数据库。

核心是:用python类操作表,用对象操作记录。
ORM把相应的类和属性操作,转换为sql语句,来操作数据库。它做了一个翻译的过程!

学习ORM,就是用什么语法,能翻译成什么样的sql语句。

看下图:

 

ORM的优点:

1.符合python语法。

2.自己写的sql语句,效率不够高。因为它直接传参,就可以使用了。

3. 不需要自己写SQL,对于类的操作,会转换成相应的SQL语句,来操作数据库。(核心功能)

4.它不属于硬编码,它不针对于MySQL。比如公司发展了,需要换成oracle数据库。

如果项目中的sql语句写死了,那么项目中的所有的sql语句,都得更换。如果用了ORM,只需要改一处,
直接修改setting.py中的数据库引擎,换成oracle,就可以了。这样,方便数据库迭代,这是它最大的优点。

ORM的缺点:

1.执行效率低。看上图,它是从上层到下层的操作。
它有一个翻译的过程。所以不如直接写SQL操作的执行效率低。
但是影响不大。真遇到这种请情况,优化SQL就可以了。
效率问题,跟SQL有很大的关系。


现在不关心ORM效率问题。除非SQL语句的造诣达到一定级别的时候,就需要使用原生SQL语句。
orm还提供了,执行原生SQL的接口。可以直接执行原生SQL。

刚开始写ORM时,一定要对应SQL语句,去写ORM

 

  • MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动
  • ORM是“对象-关系-映射”的简称。

上图有一个错误,类型是date,不是data。

sql中的表

#sql中的表                                                      

 #创建表:
     CREATE TABLE employee(                                     
                id INT PRIMARY KEY auto_increment ,                    
                name VARCHAR (20),                                      
                gender BIT default 1,                                  
                birthday DATA ,                                         
                department VARCHAR (20),                                
                salary DECIMAL (8,2) unsigned,                          
              );


  #sql中的表纪录                                                  

  #添加一条表纪录:                                                          
      INSERT employee (name,gender,birthday,salary,department)            
             VALUES   ("alex",1,"1985-12-12",8000,"保洁部");               

  #查询一条表纪录:                                                           
      SELECT * FROM employee WHERE age=24;                               

  #更新一条表纪录:                                                           
      UPDATE employee SET birthday="1989-10-24" WHERE id=1;              

  #删除一条表纪录:                                                          
      DELETE FROM employee WHERE name="alex"                             





#python的类
class Employee(models.Model):
     id=models.AutoField(primary_key=True)
     name=models.CharField(max_length=32)
     gender=models.BooleanField()
     birthday=models.DateField()
     department=models.CharField(max_length=32)
     salary=models.DecimalField(max_digits=8,decimal_places=2)


 #python的类对象
      #添加一条表纪录:
          emp=Employee(name="alex",gender=True,birthday="1985-12-12",epartment="保洁部")
          emp.save()
      #查询一条表纪录:
          Employee.objects.filter(age=24)
      #更新一条表纪录:
          Employee.objects.filter(id=1).update(birthday="1989-10-24")
      #删除一条表纪录:
          Employee.objects.filter(name="alex").delete()
View Code

class类的属性和字段是对应的。
decimal(10,2)表示最大长度为10位。小数点2位。那么整数部分,最大只能有8位。

ORM的映射关系:

复制代码
ORM引擎
python ---------------> sql

类名                        表名
属性变量                    字段
属性值                      约束条件

对象                        一条记录
复制代码

比如save(),就可以增加一条记录。所以是对象对应一条记录。

写项目的注意点:

写任何一个项目,
第一件事情,就是产品经理给你提需求。
最关键的时候,了解产品需求,逻辑关系。判断中途是否有bug!
如果做不了,一定要直接说,不能藏着。否则后期拖进度,就麻烦了。
一开始做宏观的梳理,否则后面会出现bug。导致项目推到重构!!!
对于表的设计,要慎重考虑。
早期,会经历很多碰壁的过程,这样你就能成长!
先创建表,分模块来创建表。
到了写代码的时候,反而是最简单的。
比如一个商城项目,设计表,梳理流程,花了2个月。写代码,几个星期就完成了。
View Code

单表操作

创建表

1.  创建模型

默认在应用文件下,有一个models.py文件,比如app01应用。

在app01下的models.py中创建模型:

from django.db import models

# Create your models here.

class Book(models.Model):
     id=models.AutoField(primary_key=True)
     title=models.CharField(max_length=32)
     state=models.BooleanField()
     pub_date=models.DateField()
     price=models.DecimalField(max_digits=8,decimal_places=2)
     publish=models.CharField(max_length=32)
View Code

ORM没法创建数据库,它只能操作表!
类名,首先字母要大写,它必须继承models.Model。这是固定写法!

2. 更多字段和参数

每个字段有一些特有的参数,例如,CharField需要max_length参数来指定VARCHAR数据库字段的大小。还有一些适用于所有字段的通用参数。 这些参数在文档中有详细定义,这里我们只简单介绍一些最常用的:

更多字段:

<1> CharField
        字符串字段, 用于较短的字符串.
        CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.
 
<2> IntegerField
       #用于保存一个整数.
 
<3> FloatField
        一个浮点数. 必须 提供两个参数:
         
        参数    描述
        max_digits    总位数(不包括小数点和符号)
        decimal_places    小数位数
                举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段:
                 
                models.FloatField(..., max_digits=5, decimal_places=2)
                要保存最大值一百万(小数点后保存10位)的话,你要这样定义:
                 
                models.FloatField(..., max_digits=19, decimal_places=10)
                admin 用一个文本框(<input type="text">)表示该字段保存的数据.
 
<4> AutoField
        一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段;
        自定义一个主键:my_id=models.AutoField(primary_key=True)
        如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.
 
<5> BooleanField
        A true/false field. admin 用 checkbox 来表示此类字段.
 
<6> TextField
        一个容量很大的文本字段.
        admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框).
 
<7> EmailField
        一个带有检查Email合法性的 CharField,不接受 maxlength 参数.
 
<8> DateField
        一个日期字段. 共有下列额外的可选参数:
        Argument    描述
        auto_now    当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳.
        auto_now_add    当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.
        (仅仅在admin中有意义...)
 
<9> DateTimeField
         一个日期时间字段. 类似 DateField 支持同样的附加选项.
 
<10> ImageField
        类似 FileField, 不过要校验上传对象是否是一个合法图片.#它有两个可选参数:height_field和width_field,
        如果提供这两个参数,则图片将按提供的高度和宽度规格保存.    
<11> FileField
     一个文件上传字段.
     要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime #formatting,
     该格式将被上载文件的 date/time
     替换(so that uploaded files don''t fill up the given directory).
     admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件) .
 
     注意:在一个 model 中使用 FileField 或 ImageField 需要以下步骤:
            (1)在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件.
            (出于性能考虑,这些文件并不保存到数据库.) 定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对
             WEB服务器用户帐号是可写的.
            (2) 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django
             使用 MEDIA_ROOT 的哪个子目录保存上传文件.你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT).
             出于习惯你一定很想使用 Django 提供的 get_<#fieldname>_url 函数.举例来说,如果你的 ImageField
             叫作 mug_shot, 你就可以在模板中以 {{ object.#get_mug_shot_url }} 这样的方式得到图像的绝对路径.
 
<12> URLField
      用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且
      没有返回404响应).
      admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)
 
<13> NullBooleanField
       类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项
       admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes""No" ) 来表示这种字段数据.
 
<14> SlugField
       "Slug" 是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.#它们通常用于URLs
       若你使用 Django 开发版本,你可以指定 maxlength. 若 maxlength 未指定, Django 会使用默认长度: 50.  #
       以前的 Django 版本,没有任何办法改变50 这个长度.
       这暗示了 db_index=True.
       它接受一个额外的参数: prepopulate_from, which is a list of fields from which to auto-#populate
       the slug, via JavaScript,in the object''s admin form: models.SlugField
       (prepopulate_from=("pre_name", "name"))prepopulate_from 不接受 DateTimeFields.
 
<13> XMLField
        一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema #的文件系统路径.
 
<14> FilePathField
        可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的.
        参数    描述
        path    必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目.
        Example: "/home/images".
        match    可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名. 
        注意这个正则表达式只会应用到 base filename 而不是
        路径全名. Example: "foo.*\.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif.
        recursive可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录.
        这三个参数可以同时使用.
        match 仅应用于 base filename, 而不是路径全名. 那么,这个例子:
        FilePathField(path="/home/images", match="foo.*", recursive=True)
        ...会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif
 
<15> IPAddressField
        一个字符串形式的 IP 地址, (i.e. "24.124.1.30").
<16> CommaSeparatedIntegerField
        用于存放逗号分隔的整数值. 类似 CharField, 必须要有maxlength参数.
View Code

更多参数:

(1)null
 
如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False.
 
(1)blank
 
如果为True,该字段允许不填。默认为False。
要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。
如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。
 
(2)default
 
字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用。
 
(3)primary_key
 
如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,
Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,
否则没必要设置任何一个字段的primary_key=True。
 
(4)unique
 
如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的
 
(5)choices
由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,<br>而且这个选择框的选项就是choices 中的选项。
View Code

3. settings配置

首先是注册app:
修改mysite下的settings.py文件里面的INSTALLED_APPS。注册你的app,最后一行添加,我用的app名是app01

INSTALLED_APPS = [
    ''django.contrib.admin'',
    ''django.contrib.auth'',
    ''django.contrib.contenttypes'',
    ''django.contrib.sessions'',
    ''django.contrib.messages'',
    ''django.contrib.staticfiles'',
    ''app01'',
]
View Code

不注册它,你的数据库就不知道该给哪个app创建表。

 

若想将模型转为mysql数据库中的表,需要在settings中配置:

DATABASES = {
    ''default'': {
        ''ENGINE'': ''django.db.backends.mysql'',   # 数据库引擎mysql
        ''NAME'': ''book'',       # 你要存储数据的库名,事先要创建之
        ''USER'': ''root'',      # 数据库用户名
        ''PASSWORD'': '''',      # 密码
        ''HOST'': ''localhost'', # 主机
        ''PORT'': ''3306'',      # 数据库使用的端口
    }
}
View Code

注意1:NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建 USER和PASSWORD分别是数据库的用户名和密码。

 

由于ORM不能创建数据库,需要手动创建。

进入mysql,创建数据库book。

C:\Users\xiao>mysql -u root
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 5.7.22-log MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type ''help;'' or ''\h'' for help. Type ''\c'' to clear the current input statement.

mysql> CREATE DATABASE book DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
Query OK, 1 row affected (0.01 sec)

mysql>
View Code

django连接MySQL,使用的是pymysql模块,必须得安装2个模块。否则后面会创建表不成功!或者提示no module named MySQLdb 

pip3 install pymysql
pip3 install mysqlclient

注意:某些windows电脑安装 mysqlclient会提示C++缺失。

启动项目,会报错:no module named MySQLdb 。这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb 对于py3有很大问题,所以我们需要的驱动是PyMySQL

所以,我们只需要找到app01(应用名)文件下的__init__,在里面写入:

import pymysql
pymysql.install_as_MySQLdb()

 

接下来要在pycharm的teminal中通过命令创建数据库的表了。有2条命令,分别是:

python manage.py makemigrations

E:\python_script\django框架\day5\mysite>python manage.py makemigrations
Migrations for ''app01'':
  app01\migrations\0001_initial.py
    - Create model Book
View Code

它的作用相当于 在该app下建立 migrations目录,并记录下你所有的关于modes.py的改动,比如0001_initial.py, 但是这个改动还没有作用到数据库文件

 

再输入命令:

python manage.py migrate

E:\python_script\django框架\day5\mysite>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, app01, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying app01.0001_initial... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying sessions.0001_initial... OK
View Code

它是将该改动作用到数据库文件,比如创建表,修改表字段之类的操作。

 

注意2: 如果想打印orm转换过程中的sql,需要在settings中进行如下配置:

最后一行添加即可!

LOGGING = {
    ''version'': 1,
    ''disable_existing_loggers'': False,
    ''handlers'': {
        ''console'':{
            ''level'':''DEBUG'',
            ''class'':''logging.StreamHandler'',
        },
    },
    ''loggers'': {
        ''django.db.backends'': {
            ''handlers'': [''console''],
            ''propagate'': True,
            ''level'':''DEBUG'',
        },
    }
}
View Code

演示一下:

删除数据库book

mysql> drop database book;
Query OK, 11 rows affected (1.95 sec)

mysql> CREATE DATABASE book DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
Query OK, 1 row affected (0.00 sec)
View Code

删除app01目录下的migrations文件夹

 重新执行上面2个命令

python manage.py makemigrations

E:\python_script\django框架\day5\mysite>python manage.py makemigrations
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
(0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
(0.001) SELECT VERSION(); args=None
(0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
(0.001) SHOW FULL TABLES; args=None
No changes detected
View Code

python manage.py migrate

E:\python_script\django框架\day5\mysite>python manage.py migrate
(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
(0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
(0.000) SELECT @@sql_mode; args=None
(0.001) SELECT VERSION(); args=None
(0.001) SHOW FULL TABLES; args=None
(0.000) SHOW FULL TABLES; args=None
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
(0.001) SHOW FULL TABLES; args=None
CREATE TABLE `django_migrations` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `app` varchar(255) NOT NULL, `name` varchar(255) NOT NULL, `applied` datetime(6) NOT NULL); (params None)
(0.252) CREATE TABLE `django_migrations` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `app` varchar(255) NOT NULL, `name` varchar(255) NOT NULL, `applied` datetime(6) NOT NULL); args=None
...
View Code

上面这个命令输出内容太多了,直接...代替了!

Django 2.0 学习(13):Django模板继承和静态文件

Django 2.0 学习(13):Django模板继承和静态文件

Django模板继承和静态文件

模板继承(extend)

Django模板引擎中最强大也是最复杂的部分就是模板继承了,模板继承可以让我们创建一个基本的"骨架"模板,它可以包含网页中的全部元素,并且可以定义能够被子模板覆盖的blocks。为了容易理解模板继承,我们先写一个模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}Replaceable template{% 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>

<font colot="red">这个模板,我们把它叫做base.html,它定义了一个可以用于两列排版页面的简单HTML骨架。"子模板"可以用它们的内容填充空白的blocks。在这个例子中,block标签定义了三个可以被子模板内容填充的block,block告诉模板引擎:子模板可能会覆盖掉模板中的这些位置。</font>

接下来,我们再写一个子模板:

{% extends "polls/base.html" %}        # 模板路径根据项目或者app的路径来写,笔者这里的模板位于app中

{% block title %}Child template{% endblock %}

{% block content %}
    {% for entry in blog_entries %}
        <h3>{{ entry.title }}</h3>
        <p>{{ entry.body }}</p>
    {% endfor %}
{% endblock %}

<font color="blue">extends标签是这里的关键,它告诉模板引擎这个模板继承了另一个模板。当模板系统处理这个模板时,首先定位父模板--此例中,就是"base.html"。那时模板引擎注意到base.html中的三个block标签,并用子模板中的内容来替换这些block。根据blog_entries的值,子模板输出的内容会是下面的内容:</font>

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="style.css" />
    <title>Child template</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 %}标签中的内容总是被用作备选内容。这种方式使代码得到最大程度的复用,并且使得添加内容到共享的内容区域更加简单,例如:部分范围内的导航。

<font color="red">说明:</font>

1.如果在模板中使用{% extends %}标签,它必须是模板中的第一个标签,其他的任何情况下,模板继承都将无法工作; 2.在base模版中设置越多的 {% block %} 标签越好。请记住,子模版不必定义全部父模版中的block,所以,我们可以在大多数>block中填充合理的默认内容,然后,只定义我们需要的那一个。多一点钩子总比少一点好; 3.如果发现我们在大量的模板中复制内容,那就意味着我们应该把内容移动到父模板中的一个{% block %}中; 4.有时候,想在父模板的基础上再添加点其他的,而不是完全覆盖父模板的内容,那么我们只需要在想要填充的块里,再加上 >{{ block.super }}语句,我们就可以把父模板里的东西给留下来,如:

父模板中的
{% block title %}Parent template{% endblock %}

如果我们只想子模板的结果是在后面添加一个!,则只需要在子模板中写成
{% block title %}
    {{ block.super }}!
{% endblock %}

5.为了更好的可读性,也可以给我们的 {% endblock %} 标签一个 名字 。例如:

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

6.在大型模板中,这个方法可以帮助我们清楚的看到哪个 {% block %}标签被关闭了;

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

<font color="red">注意</font>:模板一般放在app下的templates中,Django会自动去这个文件夹中找。但 假如我们每个app的templates中都有一个 index.html,当我们在views.py中使用的时候,直接写一个 render(request, ''index.html''),Django 能不能找到当前 app 的 templates 文件夹中的 index.html 文件夹呢?(答案是不一定能,有可能找错)

<font color="blue">Django模板查找机制</font>:Django 查找模板的过程是在每个 app 的 templates 文件夹中找(而不只是当前 app 中的代码,只在当前 app 的 templates 文件夹中找)。各个 app 的 templates 形成一个文件夹列表,Django 遍历这个列表,一个个文件夹进行查找,当在某一个文件夹找到的时候就停止,所有的都遍历完了还找不到指定的模板的时候就是 Template Not Found (过程类似于Python找包)。这样设计有利当然也有弊,有利是的地方是一个app可以用另一个app的模板文件,弊是有可能会找错了。所以我们使用的时候在 templates 中建立一个 app 同名的文件夹,这样就好了。这就需要把每个app中的 templates 文件夹中再建一个 app 的名称,仅和该app相关的模板放在 app/templates/app/ 目录下面。这样在使用的时候,有app作为名称的一部分,就不会混淆。

模板include

假如我们有以下模板index.html,代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div>网页公共头部部分</div>

<h2> 网页body部分 </h2>

<div>网页公共底部部分</div>

</body>
</html>

做过web开发的同学都知道大部分网页的公共头部,公共底部部分代码每个页面都一样,那么就应该将其单独拿出做为一个html, 这样修改这部分代码时候,不需要每个页面都修改, 所以在django中我们可以这么做: top.html

<div>网页公共头部部分</div>

bottom.html

<div>网页公共底部部分</div>

index.html

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <title>Title</title>  
</head>  
<body>  
  
{% include ''top.html'' %}  
  
<h2> 网页body部分 </h2>  
  
{% include ''bottom.html'' %}  
  
</body>  
</html>

我们可以使用Django模板引擎的include语法,来将单独的页面包含到当前模板页面中。有同学有疑问,那我们通过视图传递给模板的上下文,在被包含的模板中可以使用吗?可以直接使用,假如我们的视图函数如下:

def index(request):  
    return render(request, ''polls/index.html'', {''a'': 100, ''b'': 200})

该Django视图函数,传递给模板并渲染模板。

top.html修改如下:

<div>网页公共头部部分:{{ a }}</div>      # 这样使用没有任何问题

我这里有这样的一个问题,假如所有的页面都使用共同的头部top.html, 可能针对1.html 2.html 3.html所使用的头部有些样式不一样,所需top.html:

<div classs=''acss''>网页公共头部部分</div>  

但是对于5.html, 6.html使用的头部样式为:

<divbcss''>网页公共头部部分</div>  

很显然,如果直接通过include方式包含公共头部,会导致一些页面显示问题。既然部分参数不一样,include允许我们传递参数给被include的模板,我们可以使用with语法,那么问题解决如下:

{{ % include ''top.html'' with mycss=''acss'' % }}  

top.html修改如下:

<div{{mycss}}''>网页公共头部部分</div> 

被包含模板中部分参数,由我们include的时候动态指定,那么top.html就不会因为细微差别而编写多份代码了。

静态文件配置

我们自己导入的一些页面相关的包就叫做静态文件

  • 在app目录中先创建static目录;
  • 在static目录里面导入我们的JS、CSS、Jquery和Bootstrap等;
  • 在项目settings.py中添加一些配置;
STATIC_URL = ''/static/''   #这个配置就相当于下面配置的别名,如果这里的名字修改了就按照这里的名字去导入
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,"static")  #E:\day68\static 找到static路径
]
  • 导入网页相关图片、CSS、JS、Jquery等
<link rel = "stysheet",href= "/static/index.css/"> 

<link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">

Django 之 模板系统

Django 之 模板系统

Django  之  模板系统

  1、语法

Django相关语法,记住如下两种特殊符号:

1.1、{{ }} 变量相关,在模板渲染的时候替换成值
1.2 {% %} 逻辑相关的操作

  2、变量

{{变量名}} 变量名由字母数字和下划线组成

点 (.)用来获取对象的相应属性值

例子:

view

class Person():

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def talk(self):
        return ''生活静好,不存在的''

    def __str__(self):
        return "<Person {} - {}>".format(self.name, self.age)


def temp(request):
    string = ''微分,微分,你学会了吗,better,better''
    age = 12
    name_list = [''思域'', ''图灵'', ''清然'', ''柳眉'', ''雷岩'', ''浩瀚'']
    mei_dict = {
        ''name'': ''雷岩'',
        ''hobby'': ''dance'',
        ''gender'': '''',
        ''keys'': ''斯菲斯非,虚无缥缈''
    }
    now = datetime.datetime.now()
    p1 = Person(''xinxin'', 12)
    return render(request, ''temp.html'', {
        ''string'': string,
        ''age'': age,
        ''name_list'': name_list,
        ''mei_dict'': mei_dict,
        ''l1'': [1, 2, 3, 4],
        ''l2'': [5, 6, 7, 8],
        ''p1'': p1,
        ''kong'': [],
        ''num'': ''x1'',
    }
                  )

 

  模板中

<h1>{{ string}}</h1>
{# 取name_list中的第一个值 #}
<h1>{{ name_list.0 }}</h1>
{# 取字典中key = name的value值 #}
<h1>{{ mei_dict.name }}</h1>
{# 取字典中的所有key值,若keys也为key,则取的是keys对应的value值 #}
<h1>{{ mei_dict.keys}}</h1>
{# 取字典中所有的value值 #}
<h1>{{ mei_dict.values }}</h1>
{#  #}
<h1>{{ mei_dict.items }}</h1>
{# 取对象name的属性 #}
<h1>{{ p1.name }}</h1>
{# 取对象 #}
<h1>{{ p1 }}</h1>
{# .点操作只能调用不带参数的方法 #}
<h1>{{ p1.talk }}</h1>

  

注:当模板遇到一个(.)的时候,会按照如下顺序去查询:

1、在字典中查询

2、属性或者方法

3、数字索引

 

  3、Filters(过滤器)

过滤器是用来修改变量展示的结果

语法:{{value|filter_name:参数}}

default
{{value|default:"nothing"}}

 

如果value没有传值的话就显示nothing

注:TEMPLATES的OPTIONS可以增加一个选项:string_if_invalid:''找不到'',可以替代default的作用

filesizeformat

将值转化为一个人类可读的文件尺寸,最大到PB

{{filesize|filesizeformat}} 
add

给变量加参数,若都为字符串则连接

{{value|add:''2''}}
{#若是列表,则把两个列表合为一个列表#}
{{l1|add:''l2''}}

  

truncatechars

如果字符串多余指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。

参数:截断的字符数

{{value|truncatechars:8}}  
date

日期格式化

{{value|date:''Y-m-d H:i:s''}}

 也可在settings中固定日期的格式

 

# settings 中配置 
USE_L10N = False
DATETIME_FORMAT = ''Y-m-d H:i:s''
safe

Django中的模板为了安全,会对HTML和JS等语法标签进行自动转义,但是有的时候,我们并不希望这些内容被转义,这个时候就可以通过过滤器|safe的方式告诉django这段代码是安全的不必转义

{{value|safe}}

官网

https://docs.djangoproject.com/en/1.11/ref/templates/builtins/#built-in-filter-reference

 

  自定义filter

步骤:

1、在app下创建一个名为templatetags的python包 ,文件名是固定的,不能改

2、在包内创建py文件 ---my_tags.py

3、在py文件中写入:

from django import template
register = template.Library()   # register 是固定的

4、写函数加装饰器 

@register.filter
def add_str(value, arg=None):  # 函数名就是过滤器的名字,value变量  arg给变量添加额外的参数
    
    ret = ''{}__{}''.format(value,arg)
    return ret

5、使用  

{%load my_tags%}  # 导入文件

{{''zhouyou''|add_str:''zhengxing''}}

  标签tags

for
<ul>
    {% for book in book_list%}
            <li>{{book.name}}</li>
    {%endfor%}
</ul>
for 循环可用的一些参数:

forloop.counter 当前循环的索引值(从1开始)

forloop.counter0 当前循环的索引值(从0开始)

forloop.revcounter 当前循环的倒叙索引值(从1开始)

forloop.revcounter0 当前循环的倒叙索引值(从0开始)

forloop.first 当前循环是不是第一次循环(布尔值)

forloop.last 当前循环是不是最后一次循环(布尔值)

forloop.parentloop 本层循环的外层循环

empty  
<ul>
    {% for book in book_list%}
            <li>{{book.name}}</li>
    {% empty %}
        <span>空的</span>
    {%endfor%}
</ul>
if elif else
{% if book_list%}
    书籍数:{{book_list|length}}
{% elif book_em%}
    情感类:{{book_em|length}}
{% else %}
    没有书籍
{% end if%}

注:

1、条件不支持 5 > 3 >2 的连续判断 False

2、支持为and,or, == , >,<,>= ,<=,is,is not,in, not in

3、不支持算术运算

 

  静态文件 static

为避免文件路径变化而找不到静态文件,用别名

 

首先配置settings

STATIC_URL = ''/static/''

STATICFILES_DIRS = [
    os.path.join(BASE_DIR,''static'')
]

使用

{% load static%}

{% static ''静态文件路径''%}  # 完整的静态文件路径

{% get_static_prefix%}     #静态文件的别名

使用get_static_prefix

{% load static%}
<img src="{% get_static_prefix%}images/hi.jpg" alt="Hi!"/>

或者  

{% load static %}
{% get_static_prefix as STATIC_PREFIX %}

<img src="{{ STATIC_PREFIX}}images/hi.jpg" alt="Hi!" />
<img src="{{STATIC_PREFIX}}IMAGES.hi2.jpg" alt="Hello!" />

  模板继承

母版:

就是普通的HTML,提取了多个页面的公共部分

定义一些block块,让子页面重新覆盖 {% block 名字%} {% endblock %}

在母板中写block块

{% block content%} {% endblock%}

{% block js%}{%endblock%}

{% block css%}{%endblock%}

在子板中继承

{% extends ''母板的名称''%}

{% block content %}

重写block块

{% endblock%}

注意:

1、{% extends ''母版的名称''%} 写在第一行,前面不能有内容

2、{% extends ’母版的名称‘%} 模板的文件名引号要带上,不然会当作变量查找

3、要显示的内容放在block块中,其他部分不显示

4、模板中定义多个block块,一般写上css,js

 

  csrf_token

csrf(Cross-site request forgery)

跨站请求伪造:对网站的恶意利用

  组件

将常用的页面北荣如导航条,页尾信息等组件保存在单独的文件中,然后在需要使用的地方导入

{% include ''navbar.html''%}

  自定义simpletag

和自定义filter类似,只不过接收更灵活的参数。

定义注册simple_tag

@register.simple+tag(name="plus)
def plus(a,b,c):
return "{} + {} + {}".format(a,b,c)

使用自定义simple_tag

{% load app01_demo%}

{% plus "1" "2" "abc" %}

  inclusion_tag

多用于返回HTML代码段

 

步骤:

1、在app下建一个templatetags的python文件包(文件名固定)

2、在templatetags下建立一个py文件, (my_tags)

3、my_tags.py

from django import template
register = template.Library()

@register.inclusion_tag(''模板的文件名称(result.html)'')
def show_results(n):
    
    num=1 if num<1 else int(num)
    data = ["第{}页".format(i) for i in range(1,n+1)]
    return {"data":data}

4、result.html

<ul>
    
    {% for choice in data %}
    <li>{{ choice }}</li>
    {% endfor %}

</ul>

5、使用

{% load my_inclusion %}

{% show_results 10 %}

 

 

  

 

今天的关于Django模板系统-母板和继承django母版的分享已经结束,谢谢您的关注,如果想了解更多关于01 - Django模板系统、19 Django模板自定义标签和过滤器,模板继承 (extend),Django的模型层-ORM简介、Django 2.0 学习(13):Django模板继承和静态文件、Django 之 模板系统的相关知识,请在本站进行查询。

本文标签: