一、python 之禅
用一行就带你体会python的美及简洁
使用方法:在cmd中输入python然后回车,再输入import this
二、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("<h1>{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}</h1>") user_dict = Context({'user_dict': {'username': 'yafeng', 'password': 123}}) res = temp.render(user_dict) return HttpResponse(res)
"""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(基于类的视图)的基本使用
这里就得要介绍下两种名词,我们知道视图函数并不一定就是函数,也可以是类,所以就有下面的两种写法
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() ]
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("<h1>{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}</h1>") 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方法')
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <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>
3、效果图
四、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 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,发现这里有一个单例模式
2、点击LazySettings
3、去manage.py中
4、继续研究LazySettings
5、点击Settings这个类
6、得出结论
- 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) #<module 'conf.b' from 'D:\python的pycharm\ab_imp\conf\b.py'> 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())
2、HTML页面上 如何获取后端传递过来的数据
{{ 变量名 }}
(二)函数也可以传递给前端HTML文件
注意:函数传递给前端的时候会自动加括号执行,在浏览器上展示的是函数的返回值
但是模板语法并不支持给函数传参,这是限制死的
(二)类,对象也可以传递给前端HTML文件
函数和类会自动加括号,并且也可以拥有.的方法
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) ]
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("<h1>{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}</h1>") 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页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <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>
- 效果图
七、模板语法之过滤器
过滤器其实就是一堆方法,有以下几种:
过滤器:|
语法:
左边的会当做过滤器的第一个参数 | 过滤器名字右边的会当做第二个参数
| length 求数据长
| add 加法运算
| default 默认值(判断值是否为空)
| truncatewords 截取单词(可指定截取个数 三个点不算在内)
| truncatechars 截取字符(可指定截取个数 三个点算在内)
| filesizeformat 文件大小
| slice 切片
| date 日期格式化(time模块不可以,datatime可以被格式化)
| safe 取消转义(告诉浏览器我是安全的值得信赖)
前后端取消转义
前端
| safe
后端
from django.utils.safestring import mark_safe
比如:mark_safe('<h1>我是安全滴</h1>')
总结(转义的优点):
前端代码就不一定非得在前端页面书写,可以在后端下好然后传递给前端使用,这样你就可以利用到后端更多的逻辑语法
-代码演示
"""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) ]
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <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>
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("<h1>{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}</h1>") 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 = "<h1>你好啊</h1>" bbb = [] res1 = "<script>alert(123)</script>" res2 = mark_safe("<h1>你好啊</h1>") # # 给模板传递数据方式一(自己手动传) # return render(request, 'index.html', {'n':n, 'f':f,.....}) # # 给模板传递数据第二种方式 return render(request, 'index.html', locals()) # locals()会将当前名称空间中所有的变量名全部传递给html页面
- 效果图
八、模板语法之标签
模板语法的符号:
{ { } } 变量相关
{% %} 逻辑相关
那么模板语法的标签其实就是(逻辑相关)
1、for循环的内置对象forloop的原理解析
2、for循环
{% for foo in l %} <!--l = [1,2,3,4,5,6]--> {% if forloop.first %} <p>这是我的第一次</p> {% elif forloop.last %} <p>这是最后一次了啊~</p> {% else %} <p>{{ foo }}</p> {% endif %} {% empty %} <p>for循环的对象内部没有值</p> {% endfor %}
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 %}
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 %}
"""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) ]
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("<h1>{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}</h1>") 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 = "<h1>你好啊</h1>" bbb = [] res1 = "<script>alert(123)</script>" res2 = mark_safe("<h1>你好啊</h1>") # # 给模板传递数据方式一(自己手动传) # return render(request, 'index.html', {'n':n, 'f':f,.....}) # # 给模板传递数据第二种方式 return render(request, 'index.html', locals()) # locals()会将当前名称空间中所有的变量名全部传递给html页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <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 %} <!--l = [1,2,3,4,5,6]-->#} {# {% 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>
九、自定义过滤器、标签、inclusion_tag
1、前期准备工作
1、在应用名下新建一个名字必须叫做templatetags文件夹
2、在该文件夹内新建一个任意名称的py文件
3、在该py文件内 必须要先写以下两行代码
from django.template import Library
register = Library()
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> {# 自定义过滤器的使用{{ }} #}
演示
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>
演示
4、自定义过滤器与自定义标签的区别
1、自定义过滤器用{{ }},而自定义标签用{% %}
2、自定义过滤器可以在逻辑语句比如if中使用而自定义的标签则不可以
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>
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) ]
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}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <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 %} <!--l = [1,2,3,4,5,6]-->#} {# {% 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>
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("<h1>{{ user_dict }}{{ user_dict.username }}{{ user_dict.password }}</h1>") 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 = "<h1>你好啊</h1>" bbb = [] res1 = "<script>alert(123)</script>" res2 = mark_safe("<h1>你好啊</h1>") # # 给模板传递数据方式一(自己手动传) # return render(request, 'index.html', {'n':n, 'f':f,.....}) # # 给模板传递数据第二种方式 return render(request, 'index.html', locals()) # locals()会将当前名称空间中所有的变量名全部传递给html页面
<ul> {% for foo in l %} <li>{{ foo }}</li> {% endfor %} </ul>
十、模板的继承
某一各页面大部分区域都是公用的,那这个页面就可以当做模板页面
当别人继承这个页面之后 如何修改这个对应的区域
先在模板页面上通过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>Title</title> <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"> <!-- Brand and toggle get grouped for better mobile display --> <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 navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Brand</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <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="#">Link</a></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="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> <li role="separator" class="divider"></li> <li><a href="#">One more separated link</a></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">Submit</button> </form> <ul class="nav navbar-nav navbar-right"> <li><a href="#">Link</a></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="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> </ul> </li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </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 ac</a> <a href="#" class="list-group-item">Vestibulum at eros</a> </div> </div> <div class="col-md-9"> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">Panel title</h3> </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 more</a></p> </div> {% endblock %} </div> </div> </div> </div> </div> {% block js %} {% endblock %} </body> </html>
{% 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 %}
{% 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 %}
- 效果图
十一、模板的导入
将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)
# NAME = '我是暴露给用户的配置文件'
NAME = '我是项目默认的配置文件'
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()
- 演示