django源码剖析以及模板语法

一、python 之禅

  用一行就带你体会python的美及简洁

  使用方法:在cmd中输入python然后回车,再输入import this 

django源码剖析以及模板语法_第1张图片

django源码剖析以及模板语法_第2张图片

 二、render 的原理

  render原理其实就是相当于是Template以及Context的结合体,接下来我们就简单的模拟下,那么在使用之前我们需要在views.py中导入这两个模块

  from django.template import Template,Context

注意:前期我们在使用post 请求的时候记得一定要把settings总的MIDDLEWARE下的一个csrf.CsrfViewMiddleware给注释掉

- 演示代码

from django.shortcuts import render, HttpResponse, redirect

# Create your views here.
from django.template import Template, Context
# Django的render原理其实就相当于Template, Context的结合

def ab_render(request):
    temp = Template("

{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}

") user_dict = Context({'user_dict': {'username': 'yafeng', 'password': 123}}) res = temp.render(user_dict) return HttpResponse(res)
Views.py
"""day52 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^ab_render/', views.ab_render),
]
urls.py

效果图:

django源码剖析以及模板语法_第3张图片

 三、CBV(基于类的视图)的基本使用

  这里就得要介绍下两种名词,我们知道视图函数并不一定就是函数,也可以是类,所以就有下面的两种写法

  FBV: 基于函数的视图

  CBV:基于类的视图

1、CBV的基本写法

  from django.views import View

  路由中写法:

  url(r'^login/', views.Mylogin.as_view())  # 注意:一定要在对应的视图函数后面.as_view()

2、代码演示

"""day52 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^ab_render/', views.ab_render),

    # CBV路由配置
    url(r'^login/', views.Mylogin.as_view())
    # 注意一定要在对应的视图函数后面.as_view()
]
urls.py
from django.shortcuts import render, HttpResponse, redirect

# Create your views here.
from django.template import Template, Context
# Django的render原理其实就相当于Template, Context的结合

def ab_render(request):
    temp = Template("

{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}

") user_dict = Context({'user_dict': {'username': 'yafeng', 'password': 123}}) res = temp.render(user_dict) return HttpResponse(res) from django.views import View class Mylogin(View): def get(self, request): return render(request, 'login.html') def post(self, request): return HttpResponse('我是类里面的post方法')
Views.py
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js">script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js">script>

head>
<body>
<form action="" method="post">
    <input type="submit">
form>
body>
html>
login.html

3、效果图

django源码剖析以及模板语法_第4张图片

 django源码剖析以及模板语法_第5张图片

 四、CBV源码剖析

  通过刚刚的演示,我们可以看到我们朝login提交get请求会自动执行Mylogin里面的get方法,而提交post请求也会自动的执行Mylogin里面的post方法,那么为什么Mylogin可以针对不同的请求方式会自动执行相对应的方法,接下来我们就来研究下Django中的CBV源码剖析

1、研究源码的突破口

  url(r'^login/', views.Mylogin.as_view())

  猜想:

    as_view要么是类里面定义的普通函数 @staticmethod

    要么是类里面定义的绑定给类的方法 @classmethod

  所以接下来我们就点进去as_view看下,结果看源码发现是@classmethod,可以确定是绑定给类的方法

注意:看源码并一定要每一句都能够看懂 只看自己能够看懂的即可

2、演示

django源码剖析以及模板语法_第6张图片

django源码剖析以及模板语法_第7张图片

django源码剖析以及模板语法_第8张图片

django源码剖析以及模板语法_第9张图片

 五、Django settings源码剖析

1、用户可以看到的settings

  Django在配置中暴露给用户可以查看的settings源码其实不多,也就100多行,那其实这并不是Django真正的settings源码,其实Django真正的settings源码是另一个叫settings,我们可以在settings中去通过from  djjango.conf import global_settings ,settings前面是查看全局源码, 后面通过django.conf导入的settings是真正的配置文件。

总结:这里有一个结论很重要,用户自己配置了就用用户的,用户没有配置的就用Django默认的,比如之前会默认给我们加一个斜杠/

2、研究Django默认的settings源码的原理

1、点击我们之前从django.conf导入的settings,发现这里有一个单例模式

django源码剖析以及模板语法_第10张图片

 2、点击LazySettings

django源码剖析以及模板语法_第11张图片

 3、去manage.py中

django源码剖析以及模板语法_第12张图片

 4、继续研究LazySettings

django源码剖析以及模板语法_第13张图片

 5、点击Settings这个类

django源码剖析以及模板语法_第14张图片

 6、得出结论

django源码剖析以及模板语法_第15张图片

- importlib补充说明

name = 'yafeng'
# from conf import b
# #
# # print(b.name)

import importlib    # 注意:importlib这个最小识别单位只能到py文件, 不然会报错

# res = 'conf.b.name'  #ModuleNotFoundError: No module named 'conf.b.name'; 'conf.b' is not a package

res = 'conf.b'
md = importlib.import_module(res)

# print(md)   #

print(md.name)  # yafeng

六、模板语法之传值取值

1、给模板传值的两种方式

  (一)python基本数据类型全部支持传递给前端HTML文件

  1、后端给HTML传值的两种方式

  a:自己手动去传数据(指名道姓)

  return render(request, 'index.html', {'n':n, 'f': f, .....})

  b:locals()会自动将当前名称空间所有的变量名全部传递给html页面

  return render(request, 'index.html', locals())

django源码剖析以及模板语法_第16张图片

  2、HTML页面上 如何获取后端传递过来的数据

  {{ 变量名 }}

  (二)函数也可以传递给前端HTML文件

   注意:函数传递给前端的时候会自动加括号执行,在浏览器上展示的是函数的返回值

      但是模板语法并不支持给函数传参,这是限制死的

django源码剖析以及模板语法_第17张图片

     (二)类,对象也可以传递给前端HTML文件

    函数和类会自动加括号并且也可以拥有.的方法

django源码剖析以及模板语法_第18张图片

2、取值

  django模板语法取值 只有一种操作方式 句点符. 这个 点可以点索引,点key

- 演示代码

"""day52 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^ab_render/', views.ab_render),

    # CBV路由配置
    url(r'^login/', views.Mylogin.as_view()),
    # 注意一定要在对应的视图函数后面.as_view()
    # 通过观看源码我们可以得出此时上面的等价于
    # url(r'^login/', views.view)
    # 所以FBV与CBV在路由匹配上本质上是一样的 都是路由与函数内存地质的对应关系


    url(r'^index', views.index)
]
urls.py
from django.shortcuts import render, HttpResponse, redirect

# Create your views here.
from django.template import Template, Context
# Django的render原理其实就相当于Template, Context的结合

def ab_render(request):
    temp = Template("

{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}

") user_dict = Context({'user_dict': {'username': 'yafeng', 'password': 123}}) res = temp.render(user_dict) return HttpResponse(res) from django.views import View class Mylogin(View): def get(self, request): return render(request, 'login.html') def post(self, request): return HttpResponse('我是类里面的post方法') import time from datetime import datetime from django.utils.safestring import mark_safe def index(request): # python 所有的数据类型都支持传递给html页面 n = 11 f = 12.11 s = 'hello world' l = [1,2,3,4,5,6] d = {'username': 'yafeng', 'password': 123, 'hobby': ['read', {'username': ['yafeng', 'reba']}]} t = (1,2,3,4,5,6,7,) se = {1,2,3,4,5,6} b = True ff = False ss = 'kjasdklas ksd;lk akjsdkl da kjda k;lak d k;a dk ska d' sss = '卡时间 冻结 鲨科 技的 卡拉 手动 卡萨 丁卡' file_size = 32213213424 def func(): print('func被执行了') return 'from func' class MyClass(object): def get_self(self): return 'from self' @staticmethod def get_func(): return 'from func' @classmethod def get_cls(cls): return 'from cls' obj = MyClass() # # 给模板传递数据方式一(自己手动传) # return render(request, 'index.html', {'n':n, 'f':f,.....}) # # 给模板传递数据第二种方式 return render(request, 'index.html', locals()) # locals()会将当前名称空间中所有的变量名全部传递给html页面
Views.py
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js">script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js">script>

head>
<body>
{#<p>{{ n }}p>#}
{# 这种注释是模板语法的注释不会显示到浏览器上 #}

{#<p>{{ f }}p>#}
{#<p>{{ s }}p>#}
{#<p>{{ l }}p>#}
{#<p>{{ d }}p>#}
{#<p>{{ t }}p>#}
{#<p>{{ se }}p>#}
{#<p>{{ b }}p>#}
{#<p>{{ func }}p>#}

{#<p>传类名也会 自动实例化 {{ MyClass }}p>#}
{#<p>{{ MyClass.get_self }}p>#}
{#<p>{{ MyClass.get_cls }}p>#}
{#<p>{{ MyClass.get_func }}p>#}
{#<p>{{ obj }}p>#}
{#<p>{{ obj.get_cls }}p>#}
{#<p>{{ obj.get_func }}p>#}
{#<p>{{ obj.get_self }}p>#}

<p>取值p>
<p>{{ l.2 }}p>
<p>{{ d.username }}p>
<p>{{ d.password }}p>
<p>{{ d.hobby.1.username.1 }}p>



body>
html>
index.html

- 效果图

django源码剖析以及模板语法_第19张图片

django源码剖析以及模板语法_第20张图片

 七、模板语法之过滤器

  过滤器其实就是一堆方法,有以下几种:

  过滤器:|

    语法:

      左边的会当做过滤器的第一个参数 | 过滤器名字右边的会当做第二个参数 

    | length        求数据长

    | add           加法运算

    | default        默认值(判断值是否为空)

    | truncatewords   截取单词(可指定截取个数  三个点不算在内) 

    | truncatechars   截取字符(可指定截取个数  三个点算在内)

    | filesizeformat     文件大小

    | slice              切片

    | date              日期格式化(time模块不可以,datatime可以被格式化)

    | safe              取消转义(告诉浏览器我是安全的值得信赖)

前后端取消转义

  前端

    | safe

  后端

    from django.utils.safestring import mark_safe

    比如:mark_safe('

我是安全滴

')

总结(转义的优点):

  前端代码就不一定非得在前端页面书写,可以在后端下好然后传递给前端使用,这样你就可以利用到后端更多的逻辑语法

-代码演示

"""day52 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^ab_render/', views.ab_render),

    # CBV路由配置
    url(r'^login/', views.Mylogin.as_view()),
    # 注意一定要在对应的视图函数后面.as_view()
    # 通过观看源码我们可以得出此时上面的等价于
    # url(r'^login/', views.view)
    # 所以FBV与CBV在路由匹配上本质上是一样的 都是路由与函数内存地质的对应关系


    url(r'^index', views.index)
]
urls.py
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js">script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js">script>

head>
<body>
{#<p>{{ n }}p>#}
{# 这种注释是模板语法的注释不会显示到浏览器上 #}

{#<p>{{ f }}p>#}
{#<p>{{ s }}p>#}
{#<p>{{ l }}p>#}
{#<p>{{ d }}p>#}
{#<p>{{ t }}p>#}
{#<p>{{ se }}p>#}
{#<p>{{ b }}p>#}
{#<p>{{ func }}p>#}

{#<p>传类名也会 自动实例化 {{ MyClass }}p>#}
{#<p>{{ MyClass.get_self }}p>#}
{#<p>{{ MyClass.get_cls }}p>#}
{#<p>{{ MyClass.get_func }}p>#}
{#<p>{{ obj }}p>#}
{#<p>{{ obj.get_cls }}p>#}
{#<p>{{ obj.get_func }}p>#}
{#<p>{{ obj.get_self }}p>#}

{#<p>取值p>#}
{#<p>{{ l.2 }}p>#}
{#<p>{{ d.username }}p>#}
{#<p>{{ d.password }}p>#}
{#<p>{{ d.hobby.1.username.1 }}p>#}

<p>过滤器p>
<p>求数据长度:{{ s|length }}p>
<p>加法运算:{{ n|add:10 }}、{{ s|add:13132 }}、{{ s|add:'DSB' }}p>
<p>默认值(判断值是否为空):{{ b|default:'这个b布尔值是True' }}、{{ ff|default:'这个ff布尔值是Flase' }}p>
<p>截取字符(截取5个字符 三个点也算):{{ s|truncatechars:8 }}p>
<p>截取单词(截取8个单词 三个点不算):{{ ss|truncatewords:8 }}、{{ sss|truncatewords:4 }}p>
<p>文件大小:{{ file_size|filesizeformat }}p>
<p>切片操作:{{ s|slice:'0:2' }}、{{ s|slice:"0:8:2" }}p>
<p>日期格式化:{{ ddd|date:'Y年/m月/d日' }}p>
<p>转义:{{ res|safe }}、{{ res1 }}、后端直接标识安全:{{ res2 }}p>

body>
html>
index.html
from django.shortcuts import render, HttpResponse, redirect

# Create your views here.
from django.template import Template, Context
# Django的render原理其实就相当于Template, Context的结合

def ab_render(request):
    temp = Template("

{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}

") user_dict = Context({'user_dict': {'username': 'yafeng', 'password': 123}}) res = temp.render(user_dict) return HttpResponse(res) from django.views import View class Mylogin(View): def get(self, request): return render(request, 'login.html') def post(self, request): return HttpResponse('我是类里面的post方法') import time from datetime import datetime from django.utils.safestring import mark_safe def index(request): # python 所有的数据类型都支持传递给html页面 n = 11 f = 12.11 s = 'hello world' l = [1,2,3,4,5,6] d = {'username': 'yafeng', 'password': 123, 'hobby': ['read', {'username': ['yafeng', 'reba']}]} t = (1,2,3,4,5,6,7,) se = {1,2,3,4,5,6} b = True ff = False ss = 'kjasdklas ksd;lk akjsdkl da kjda k;lak d k;a dk ska d' sss = '卡时间 冻结 鲨科 技的 卡拉 手动 卡萨 丁卡' file_size = 32213213424 def func(): print('func被执行了') return 'from func' class MyClass(object): def get_self(self): return 'from self' @staticmethod def get_func(): return 'from func' @classmethod def get_cls(cls): return 'from cls' obj = MyClass() ttt = time.time() ddd = datetime.now() res = "

你好啊

" bbb = [] res1 = "" res2 = mark_safe("

你好啊

") # # 给模板传递数据方式一(自己手动传) # return render(request, 'index.html', {'n':n, 'f':f,.....}) # # 给模板传递数据第二种方式 return render(request, 'index.html', locals()) # locals()会将当前名称空间中所有的变量名全部传递给html页面
Views.py

- 效果图

django源码剖析以及模板语法_第21张图片

django源码剖析以及模板语法_第22张图片

django源码剖析以及模板语法_第23张图片

 八、模板语法之标签

  模板语法的符号:

    { {  } }   变量相关

    {% %}   逻辑相关

  那么模板语法的标签其实就是(逻辑相关)

1、for循环的内置对象forloop的原理解析

django源码剖析以及模板语法_第24张图片

 2、for循环

{% for foo in l %}  
   {% if forloop.first %}
      <p>这是我的第一次p>
   {% elif forloop.last %}
      <p>这是最后一次了啊~p>
   {% else %}
      <p>{{ foo }}p>
   {% endif %}
   {% empty %}
       <p>for循环的对象内部没有值p>
{% endfor %}

django源码剖析以及模板语法_第25张图片

 3、for循环之取字典

{% for foo in d.keys %}
    <p>{{ foo }}p>
{% endfor %}


{% for foo in d.values %}
    <p>{{ foo }}p>
{% endfor %}

{% for foo in d.items %}
    <p>{{ foo }}p>
{% endfor %}

django源码剖析以及模板语法_第26张图片

4、for循环之with起别名

<p>当一个值获取的步骤非常繁琐 但是又需要在很多地方用到 我们可以用起别名的方式来简化代码p>
{% with  d.hobby.1.username.1 as eg  %}
    <p>别名只能在with内使用:{{ eg }}p>
    <p>{{ d.hobby.1.username.1 }}p>
{% endwith %}
django源码剖析以及模板语法_第27张图片
"""day52 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^ab_render/', views.ab_render),

    # CBV路由配置
    url(r'^login/', views.Mylogin.as_view()),
    # 注意一定要在对应的视图函数后面.as_view()
    # 通过观看源码我们可以得出此时上面的等价于
    # url(r'^login/', views.view)
    # 所以FBV与CBV在路由匹配上本质上是一样的 都是路由与函数内存地质的对应关系


    url(r'^index', views.index)
]
urls.py
from django.shortcuts import render, HttpResponse, redirect

# Create your views here.
from django.template import Template, Context
# Django的render原理其实就相当于Template, Context的结合

def ab_render(request):
    temp = Template("

{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}

") user_dict = Context({'user_dict': {'username': 'yafeng', 'password': 123}}) res = temp.render(user_dict) return HttpResponse(res) from django.views import View class Mylogin(View): def get(self, request): return render(request, 'login.html') def post(self, request): return HttpResponse('我是类里面的post方法') import time from datetime import datetime from django.utils.safestring import mark_safe def index(request): # python 所有的数据类型都支持传递给html页面 n = 11 f = 12.11 s = 'hello world' l = [1,2,3,4,5,6] d = {'username': 'yafeng', 'password': 123, 'hobby': ['read', {'username': ['yafeng', 'reba']}]} t = (1,2,3,4,5,6,7,) se = {1,2,3,4,5,6} b = True ff = False ss = 'kjasdklas ksd;lk akjsdkl da kjda k;lak d k;a dk ska d' sss = '卡时间 冻结 鲨科 技的 卡拉 手动 卡萨 丁卡' file_size = 32213213424 def func(): print('func被执行了') return 'from func' class MyClass(object): def get_self(self): return 'from self' @staticmethod def get_func(): return 'from func' @classmethod def get_cls(cls): return 'from cls' obj = MyClass() ttt = time.time() ddd = datetime.now() res = "

你好啊

" bbb = [] res1 = "" res2 = mark_safe("

你好啊

") # # 给模板传递数据方式一(自己手动传) # return render(request, 'index.html', {'n':n, 'f':f,.....}) # # 给模板传递数据第二种方式 return render(request, 'index.html', locals()) # locals()会将当前名称空间中所有的变量名全部传递给html页面
Views.py
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js">script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js">script>

head>
<body>
{#<p>{{ n }}p>#}
{# 这种注释是模板语法的注释不会显示到浏览器上 #}

{#<p>{{ f }}p>#}
{#<p>{{ s }}p>#}
{#<p>{{ l }}p>#}
{#<p>{{ d }}p>#}
{#<p>{{ t }}p>#}
{#<p>{{ se }}p>#}
{#<p>{{ b }}p>#}
{#<p>{{ func }}p>#}

{#<p>传类名也会 自动实例化 {{ MyClass }}p>#}
{#<p>{{ MyClass.get_self }}p>#}
{#<p>{{ MyClass.get_cls }}p>#}
{#<p>{{ MyClass.get_func }}p>#}
{#<p>{{ obj }}p>#}
{#<p>{{ obj.get_cls }}p>#}
{#<p>{{ obj.get_func }}p>#}
{#<p>{{ obj.get_self }}p>#}

{#<p>取值p>#}
{#<p>{{ l.2 }}p>#}
{#<p>{{ d.username }}p>#}
{#<p>{{ d.password }}p>#}
{#<p>{{ d.hobby.1.username.1 }}p>#}

{#<p>过滤器p>#}
{#<p>求数据长度:{{ s|length }}p>#}
{#<p>加法运算:{{ n|add:10 }}、{{ s|add:13132 }}、{{ s|add:'DSB' }}p>#}
{#<p>默认值(判断值是否为空):{{ b|default:'这个b布尔值是True' }}、{{ ff|default:'这个ff布尔值是Flase' }}p>#}
{#<p>截取字符(截取5个字符 三个点也算):{{ s|truncatechars:8 }}p>#}
{#<p>截取单词(截取8个单词 三个点不算):{{ ss|truncatewords:8 }}、{{ sss|truncatewords:4 }}p>#}
{#<p>文件大小:{{ file_size|filesizeformat }}p>#}
{#<p>切片操作:{{ s|slice:'0:2' }}、{{ s|slice:"0:8:2" }}p>#}
{#<p>日期格式化:{{ ddd|date:'Y年/m月/d日' }}p>#}
{#<p>转义:{{ res|safe }}、{{ res1 }}、后端直接标识安全:{{ res2 }}p>#}

<p>标签p>
{#{% for foo in l %}#}
{#    <p>{{ forloop }}p>  {# forloop是for循环内置的对象 #}
{#{% endfor %}#}

{#{% for foo in l %}  #}
{#    {% if forloop.first %}#}
{#        <p>这是我的第一次p>#}
{#    {% elif forloop.last %}#}
{#        <p>这是最后一次了啊~p>#}
{#    {% else %}#}
{#        <p>{{ foo }}p>#}
{#    {% endif %}#}
{#    {% empty %}#}
{#        <p>for循环的对象内部没有值p>#}
{##}
{#    #}
{#{% endfor %}#}

{% for foo in d.keys %}
    <p>{{ foo }}p>
{% endfor %}


{% for foo in d.values %}
    <p>{{ foo }}p>
{% endfor %}

{% for foo in d.items %}
    <p>{{ foo }}p>
{% endfor %}

<p>当一个值获取的步骤非常繁琐 但是又需要在很多地方用到 我们可以用起别名的方式来简化代码p>
{% with  d.hobby.1.username.1 as eg  %}
    <p>别名只能在with内使用:{{ eg }}p>
    <p>{{ d.hobby.1.username.1 }}p>
{% endwith %}

body>
html>
index.html

九、自定义过滤器、标签、inclusion_tag

1、前期准备工作

  1、在应用名下新建一个名字必须叫做templatetags文件夹

  2、在该文件夹内新建一个任意名称的py文件

  3、在该py文件内 必须要先写以下两行代码

    from django.template import Library

    register = Library()

django源码剖析以及模板语法_第28张图片

django源码剖析以及模板语法_第29张图片

2、自定义过滤器

from django.template import Library

register = Library()    # 这两行代码一定要先写好


# 自定义过滤器
@register.filter(name='my_sum')
def index(a, b):   # 过滤器最多最多接收两个参数
    return a + b
<p>自定义过滤器的使用p>
{% load mytag %}      {# 字使用自定义过滤器之前得先把他导入过来 
<p>{{ 10|my_sum:90 }}p>   {# 自定义过滤器的使用{{  }} #}

演示

django源码剖析以及模板语法_第30张图片

 3、自定义标签

# 自定义标签
@register.simple_tag(name='my_baby')
def xxx(a, b, c, d):
     return '%s?%s?%s?%s'%(a,b,c,d)
<p>自定义标签的使用p>    {# 自定义标签的使用{%  %} #}
{% load mytag %}
<p>{% my_baby 1 2 3 'hello baby' %}p>

演示

django源码剖析以及模板语法_第31张图片

4、自定义过滤器与自定义标签的区别

1、自定义过滤器用{{ }},而自定义标签用{% %}

2、自定义过滤器可以在逻辑语句比如if中使用而自定义的标签则不可以

django源码剖析以及模板语法_第32张图片

django源码剖析以及模板语法_第33张图片

5、自定义inclusion_tag

  调用inclusion_tag 是作用到HTML页面上,可以通过传参数让他帮你渲染到某一片区域

然后放到页面的某一个位置,可以通过参数动态的改变HTML页面的一些内容

# 自定义inclusion_tag
@register.inclusion_tag('demo.html', name='myin')
def index1(n):
    l = []
    for i in range(n):
        l.append(i)

    # 将列表传递给demo.html
    # return locals()
    return {'l':l}
<p>自定义inclusion_tag的使用p>
{% load mytag %}
{% myin 5 %}
body>
html>
<ul>
    {% for foo in l %}
        <li>{{ foo }}li>
    {% endfor %}
ul>
demo.py

django源码剖析以及模板语法_第34张图片

6、总结

  在前端页面上使用自定义的过滤器,标签,inclusion_tag都要统一先导入

{% load 你自定义的py文件名(比如mytag) %}

 
 
"""day52 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^ab_render/', views.ab_render),

    # CBV路由配置
    url(r'^login/', views.Mylogin.as_view()),
    # 注意一定要在对应的视图函数后面.as_view()
    # 通过观看源码我们可以得出此时上面的等价于
    # url(r'^login/', views.view)
    # 所以FBV与CBV在路由匹配上本质上是一样的 都是路由与函数内存地质的对应关系
    
    
    url(r'^index', views.index)
]
urls.py
from django.template import Library

register = Library()


# 自定义过滤器
@register.filter(name='my_sum')
def index(a, b):   # 过滤器最多最多接收两个参数
    return a + b

# 自定义标签
@register.simple_tag(name='my_baby')
def xxx(a, b, c, d):
     return '%s?%s?%s?%s'%(a,b,c,d)


# 自定义inclusion_tag
@register.inclusion_tag('demo.html', name='myin')
def index1(n):
    l = []
    for i in range(n):
        l.append(i)

    # 将列表传递给demo.html
    # return locals()
    return {'l':l}
mytag.py
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js">script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js">script>

head>
<body>
{#<p>{{ n }}p>#}
{# 这种注释是模板语法的注释不会显示到浏览器上 #}

{#<p>{{ f }}p>#}
{#<p>{{ s }}p>#}
{#<p>{{ l }}p>#}
{#<p>{{ d }}p>#}
{#<p>{{ t }}p>#}
{#<p>{{ se }}p>#}
{#<p>{{ b }}p>#}
{#<p>{{ func }}p>#}

{#<p>传类名也会 自动实例化 {{ MyClass }}p>#}
{#<p>{{ MyClass.get_self }}p>#}
{#<p>{{ MyClass.get_cls }}p>#}
{#<p>{{ MyClass.get_func }}p>#}
{#<p>{{ obj }}p>#}
{#<p>{{ obj.get_cls }}p>#}
{#<p>{{ obj.get_func }}p>#}
{#<p>{{ obj.get_self }}p>#}

{#<p>取值p>#}
{#<p>{{ l.2 }}p>#}
{#<p>{{ d.username }}p>#}
{#<p>{{ d.password }}p>#}
{#<p>{{ d.hobby.1.username.1 }}p>#}

{#<p>过滤器p>#}
{#<p>求数据长度:{{ s|length }}p>#}
{#<p>加法运算:{{ n|add:10 }}、{{ s|add:13132 }}、{{ s|add:'DSB' }}p>#}
{#<p>默认值(判断值是否为空):{{ b|default:'这个b布尔值是True' }}、{{ ff|default:'这个ff布尔值是Flase' }}p>#}
{#<p>截取字符(截取5个字符 三个点也算):{{ s|truncatechars:8 }}p>#}
{#<p>截取单词(截取8个单词 三个点不算):{{ ss|truncatewords:8 }}、{{ sss|truncatewords:4 }}p>#}
{#<p>文件大小:{{ file_size|filesizeformat }}p>#}
{#<p>切片操作:{{ s|slice:'0:2' }}、{{ s|slice:"0:8:2" }}p>#}
{#<p>日期格式化:{{ ddd|date:'Y年/m月/d日' }}p>#}
{#<p>转义:{{ res|safe }}、{{ res1 }}、后端直接标识安全:{{ res2 }}p>#}

{#<p>标签p>#}
{#{% for foo in l %}#}
{#    <p>{{ forloop }}p>  {# forloop是for循环内置的对象 #}
{#{% endfor %}#}

{#{% for foo in l %}  #}
{#    {% if forloop.first %}#}
{#        <p>这是我的第一次p>#}
{#    {% elif forloop.last %}#}
{#        <p>这是最后一次了啊~p>#}
{#    {% else %}#}
{#        <p>{{ foo }}p>#}
{#    {% endif %}#}
{#    {% empty %}#}
{#        <p>for循环的对象内部没有值p>#}
{##}
{#    #}
{#{% endfor %}#}
{##}
{#{% for foo in d.keys %}#}
{#    <p>{{ foo }}p>#}
{#{% endfor %}#}
{##}
{##}
{#{% for foo in d.values %}#}
{#    <p>{{ foo }}p>#}
{#{% endfor %}#}
{##}
{#{% for foo in d.items %}#}
{#    <p>{{ foo }}p>#}
{#{% endfor %}#}
{##}
{#<p>当一个值获取的步骤非常繁琐 但是又需要在很多地方用到 我们可以用起别名的方式来简化代码p>#}
{#{% with  d.hobby.1.username.1 as eg  %}#}
{#    <p>别名只能在with内使用:{{ eg }}p>#}
{#    <p>{{ d.hobby.1.username.1 }}p>#}
{#{% endwith %}#}


{#<p>自定义过滤器的使用p>#}
{#{% load mytag %}      {# 字使用自定义过滤器之前得先把他导入过来#}
{#<p>{{ 10|my_sum:90 }}p>   {# 自定义过滤器的使用{{  }} #}
{##}
{#<p>自定义标签的使用p>    {# 自定义标签的使用{%  %} #}
{#{% load mytag %}#}
{#<p>{% my_baby 1 2 3 'hello baby' %}p>#}

{#<p>自定义的过滤器可以在逻辑语句中而自定义的标签不可以p>#}
{#{% if 10|my_sum:100 %}#}
{#    <p>条件成立p>#}
{#{% endif %}#}

{#{% if my_baby 1 2 3 4 %}#}
{#    <p>条件成立p>#}
{#{% endif %}#}

<p>自定义inclusion_tag的使用p>
{% load mytag %}
{% myin 5 %}
body>
html>
index.html
from django.shortcuts import render, HttpResponse, redirect

# Create your views here.
from django.template import Template, Context
# Django的render原理其实就相当于Template, Context的结合

def ab_render(request):
    temp = Template("

{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}

") user_dict = Context({'user_dict': {'username': 'yafeng', 'password': 123}}) res = temp.render(user_dict) return HttpResponse(res) from django.views import View class Mylogin(View): def get(self, request): return render(request, 'login.html') def post(self, request): return HttpResponse('我是类里面的post方法') import time from datetime import datetime from django.utils.safestring import mark_safe def index(request): # python 所有的数据类型都支持传递给html页面 n = 11 f = 12.11 s = 'hello world' l = [1,2,3,4,5,6] d = {'username': 'yafeng', 'password': 123, 'hobby': ['read', {'username': ['yafeng', 'reba']}]} t = (1,2,3,4,5,6,7,) se = {1,2,3,4,5,6} b = True ff = False ss = 'kjasdklas ksd;lk akjsdkl da kjda k;lak d k;a dk ska d' sss = '卡时间 冻结 鲨科 技的 卡拉 手动 卡萨 丁卡' file_size = 32213213424 def func(): print('func被执行了') return 'from func' class MyClass(object): def get_self(self): return 'from self' @staticmethod def get_func(): return 'from func' @classmethod def get_cls(cls): return 'from cls' obj = MyClass() ttt = time.time() ddd = datetime.now() res = "

你好啊

" bbb = [] res1 = "" res2 = mark_safe("

你好啊

") # # 给模板传递数据方式一(自己手动传) # return render(request, 'index.html', {'n':n, 'f':f,.....}) # # 给模板传递数据第二种方式 return render(request, 'index.html', locals()) # locals()会将当前名称空间中所有的变量名全部传递给html页面
Views.py
<ul>
    {% for foo in l %}
        <li>{{ foo }}li>
    {% endfor %}
ul>
demo.html

十、模板的继承

  某一各页面大部分区域都是公用的,那这个页面就可以当做模板页面

  当别人继承这个页面之后 如何修改这个对应的区域

  先在模板页面上通过block实现划定区域

  {%  block content %}   # block后面加你的别名

    模板页面内容

  {%  endblock %}

  子页面中先导入整个模板

  {%  extends  '模板页面.html'%}  ##模板的继承

    修改特定的区域 通过事先划定好的区域名称

    {%  block content %}

      子页面内容

    {%  endblock %}

  通常情况下,模板页面上应该有三块区域   

    {%  block css %}

      模板页面内容

    {%  endblock %}

    {%  block content %}

      模板页面内容

    {%  endblock %}

    {%  block js %}

      模板页面内容

    {%  endblock %}

  一般情况下 模板的block快越多 可扩展性越强,,除此之外还支持子页面调用父页面对应区域 的内容  {{ block.super  }}

- 代码

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js">script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js">script>
    {% block css %}

    {% endblock %}
head>
<body>
<nav class="navbar navbar-inverse">
  <div class="container-fluid">
    
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigationspan>
        <span class="icon-bar">span>
        <span class="icon-bar">span>
        <span class="icon-bar">span>
      button>
      <a class="navbar-brand" href="#">Branda>
    div>

    
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link <span class="sr-only">(current)span>a>li>
        <li><a href="#">Linka>li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret">span>a>
          <ul class="dropdown-menu">
            <li><a href="#">Actiona>li>
            <li><a href="#">Another actiona>li>
            <li><a href="#">Something else herea>li>
            <li role="separator" class="divider">li>
            <li><a href="#">Separated linka>li>
            <li role="separator" class="divider">li>
            <li><a href="#">One more separated linka>li>
          ul>
        li>
      ul>
      <form class="navbar-form navbar-left">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        div>
        <button type="submit" class="btn btn-default">Submitbutton>
      form>
      <ul class="nav navbar-nav navbar-right">
        <li><a href="#">Linka>li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret">span>a>
          <ul class="dropdown-menu">
            <li><a href="#">Actiona>li>
            <li><a href="#">Another actiona>li>
            <li><a href="#">Something else herea>li>
            <li role="separator" class="divider">li>
            <li><a href="#">Separated linka>li>
          ul>
        li>
      ul>
    div>
  div>
nav>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-3">
            <div class="list-group">
              <a href="/mdzz/" class="list-group-item active">
                首页
              a>
              <a href="/reg/" class="list-group-item">注册a>
              <a href="/loginn/" class="list-group-item">登录a>
              <a href="#" class="list-group-item">Porta ac consectetur aca>
              <a href="#" class="list-group-item">Vestibulum at erosa>
            div>
        div>
        <div class="col-md-9">
            <div class="panel panel-primary">
              <div class="panel-heading">
                <h3 class="panel-title">Panel titleh3>
              div>
              <div class="panel-body">
                {% block content %}
                <div class="jumbotron">
                  <h1>Hello, world!h1>
                  <p>...p>
                  <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn morea>p>
                div>
                {% endblock %}
              div>
            div>
        div>
    div>
div>

{% block js %}

{% endblock %}
body>
html>
mdzz.hyml
{% extends 'mdzz.html' %}

{% block css %}
    <style>
        h2  {
            color: red;
        }
    style>
{% endblock %}

{% block content %}
    {% include 'left.html' %}



<h2 class="text-center">登录页面h2>
    <form action="">
        <p>username:
            <input type="text" class="form-control">
        p>
    <p>password:
            <input type="text" class="form-control">
        p>
        <input type="submit" class="btn btn-primary">
    form>
    {{ block.super }}  {# 继承引用模板的内容 #}

{% endblock %}


{% block js %}
{#    <script>#}
{#        alert(123)#}
{#    script>#}
{% endblock %}
loginn.html
{% extends 'mdzz.html' %}   {# extend把就可以继承mdzz #}

{% block css %}
    <style>
        h2 {
            color: green;
        }
    style>
{% endblock %}


{% block content %}
<h2 class="text-center">注册页面h2>
    <form action="">
        <p>username:
            <input type="text" class="form-control">
        p>
    <p>password:
            <input type="text" class="form-control">
        p>
        <input type="submit" class="btn btn-danger">
    form>
    {{ block.super }}
    {{ block.super }}
    {{ block.super }}
    {{ block.super }}
    {{ block.super }}
    {{ block.super }}
    {{ block.super }}
{% endblock %}


{% block js %}
{#    <script>#}
{#        alert(666)#}
{#    script>#}
{% endblock %}
reg.html

- 效果图

django源码剖析以及模板语法_第35张图片

django源码剖析以及模板语法_第36张图片

 django源码剖析以及模板语法_第37张图片

 十一、模板的导入

   将HTML页面当做模块使用  哪里需要就导到那里去 通常这个HTML页面都是不完整的

方法:{%  include  ‘模板.html’  %}

十二、基于django settings源码实现插拔式设计

import os
import sys


BASE_DIR = os.path.dirname(__file__)
sys.path.append(BASE_DIR)


if __name__ == '__main__':
     # 项目启动就应该朝全局的大字典中设置键值对
    os.environ['xxx'] = 'conf.settings'
    from lib.conf import settings
    print(settings.NAME)
start.py
# NAME = '我是暴露给用户的配置文件'
conf下的配置
NAME = '我是项目默认的配置文件'
lib默认的配置
import importlib
import os
from lib.conf import global_settings


class Settings(object):
    def __init__(self):
        # 先循环遍历项目默认的全局配置文件
        for name in dir(global_settings):
            # 判断变量名是否是大写
            if name.isupper():
                # 键值对设置给对象
                k = name   # NAME
                v = getattr(global_settings, name)   # yafeng
                setattr(self, k, v)


        # 先获取暴露给用户的配置文件的字符串路径
        module_path = os.environ.get('xxx')   # conf.settings
        # 里面importlib模块 导入settings文件
        md = importlib.import_module(module_path) # md = settings

        for name in dir(md):
            # 判断变量名是否是大写
            if name.isupper():
                # 键值对设置给对象
                k = name   # NAME
                v = getattr(md, name)   # yafeng
                setattr(self, k, v)


settings = Settings()
lib下的conf下的__init__

- 演示

django源码剖析以及模板语法_第38张图片

django源码剖析以及模板语法_第39张图片

 

 

 

 

 

 

 


 

你可能感兴趣的:(django源码剖析以及模板语法)