今日内容:
标签过滤器自定义标签,过滤器,inclusion_tag模板的继承
模板的导入
首先来说一下render内部原理和FBV与CBV
三板斧
FBV
render返回一个html页面 并且还能够给该页面传数据 render内部原理
from django.template import Template,Context def index(request): temp = Template('<h1>{{ user }}</h1>') con = Context({"user":{"name":'jason',"password":'123'}}) res = temp.render(con) print(res) return HttpResponse(res)
FBV与CBV
FBV与CBV
视图函数并不只是指函数,也可以是类
FBV(基于函数的视图)面向函数式编程
CBV(基于类的视图)面向对象式编程
# 问题:基于CBV的视图函数
get请求来就会走类里面的get方法,post请求来就会走类里面post方法,这是为什么了???
#CBV
urls.py中 url(r'^login/',views.MyLogin.as_view()) views.py中 from django.views import View
from django.views import View # from django.conf import settings class MyLogin(View): def get(self,request): print("from MyLogin get方法") return render(request,'login.html') def post(self,request): return HttpResponse("from MyLogin post方法")
研究方向:
1.从url入手
View Code
什么settings里面的变量都要用大写的,用小写的没用:
django settings源码
1 django settings源码 2 前提: 3 1.django除了暴露给用户一个settings.py配置文件之外 自己内部还有一个全局的配置文件 4 2.我们在使用配置文件的时候 可以直接直接导入暴露给用户的settings.py也可以使用django全局的配置文件 并且后者居多 5 from django.conf import settings 6 3.django的启动入口是manage.py 7 8 import os 9 import sys 10 11 if __name__ == "__main__": 12 # django在启动的时候 就会往全局的大字典中设置一个键值对 值是暴露给用户的配置文件的路径字符串 13 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day54.settings") 14 15 class Settings(object): 16 def __init__(self, settings_module): # settings_module = 'day54.settings' 17 # update this dict from global settings (but only for ALL_CAPS settings) 18 for setting in dir(global_settings): # django全局配置文件 19 # dir获取django全局配置文件中所有的变量名 20 if setting.isupper(): # 判断文件中的变量名是否是大写 如果是大写才会执行/生效 21 setattr(self, setting, getattr(global_settings, setting)) # 给settings对象设置键值对 22 # 给settings对象设置键值对 settings[配置文件中大写的变量名] = 配置文件中大写的变量名所对应的值 23 24 # store the settings module in case someone later cares 25 self.SETTINGS_MODULE = settings_module # 'day54.settings' 26 27 mod = importlib.import_module(self.SETTINGS_MODULE) # mod = 模块settings(暴露给用户的配置文件) 28 for setting in dir(mod): # for循环获取暴露给用户的配置文件中所有的变量名 29 if setting.isupper(): # 判断变量名是否是大写 30 setting_value = getattr(mod, setting) # 获取大写的变量名所对应的值 31 setattr(self, setting, setting_value) # 给settings对象设置键值对 32 """ 33 d = {} 34 d['username'] = 'jason' 35 d['username'] = 'egon' 36 用户如果配置了就用用户的 37 用户如果没有配置就用系统默认的 38 其实本质就是利用字典的键存在就是替换的原理 实现了用户配置就用用户的用户没配置就用默认的 39 """ 40 41 class LazySettings(LazyObject): 42 def _setup(self, name=None): 43 # os.environ你可以把它看成是一个全局的大字典 44 settings_module = os.environ.get(ENVIRONMENT_VARIABLE) # 从大字典中取值键为DJANGO_SETTINGS_MODULE所对应的值:day54.settings 45 # settings_module = 'day54.settings' 46 self._wrapped = Settings(settings_module) # Settings('day54.settings') 47 48 49 settings = LazySettings() # 单例模式
模板层
模板语法:一共分为俩大类
{{ }} 跟变量相关的
{%%} 跟逻辑相关的
后端给前端传值的方式:
后端朝前端页面传递数据的方式 # 第一种 return render(request,'index.html',{'n':n}) # 第二种 return render(request,'index.html',locals()) # 将当前所在的名称空间中的名字全部传递给前端页面 后端传函数名到前端,会自动加括号调用,但是不支持传参
详情代码:
前端:
1 <p>{{ n }}</p> 2 <p>{{ f }}</p> 3 <p>{{ s }}</p> 4 <p>{{ l }}</p> 5 <p>{{ d }}</p> 6 <p>{{ t }}</p> 7 <p>{{ se }}</p> 8 <p>{{ index }}</p> 9 10 <p>{{ obj }}</p> 11 <p>{{ obj.get_self }}</p> 12 <p>{{ obj.get_cls }}</p> 13 <p>{{ obj.get_static }}</p>
后端:
1 def reg(request): 2 # 以下的数据类型都是可以被传递给前端的 3 n = 0 4 # ss = '' 5 f = 1.11 6 s = '你妹的' 7 l = [1, 2, 3, 4, 5, 6] 8 d = {"name": 'jason', 'password': 123} 9 t = (1, 2, 3, 4, 5) 10 se = {1, 2, 3, 4, 5, 6, 7, } 11 12 def index(): 13 print('index') 14 15 class Demo(object): 16 def get_self(self): 17 return '绑定给对象的方法' 18 @classmethod 19 def get_cls(cls): 20 return '绑定给类的方法' 21 @staticmethod 22 def get_static(): 23 return '我是静态方法 其实就是函数' 24 obj = Demo() 25 26 # 给模板传值的方式 27 # 方式1 通过字典的键值对方式,然后指名道姓的一个个传 28 # return render(request,'reg.html',{'n':n,'f':f}) 29 # 方式2 而用一下locals()会将它所在的名称空间中所有的名字全部传递给前端 30 # 这个方法虽然好用,但是在某些情况下会造成资源的浪费,这里只是为了 31 return render(request,'reg.html',locals())
模板语法之过滤器:
前端: |safe 后端: from django.utils.safestring import mark_safe zzz = mark_safe('<h1>阿萨德搜啊第三款垃圾袋</h1>') <h1>模板语法之过滤器:它内部的原理就是(会将|前面的当做第一个参数传入标签中)</h1> <p>{{ l|length }} 计算标签内的数据是多长 </p> <p>{{ n|length }}必须要是放在容器里面才能计算长度</p> <p>{{ ss|default:'当|左边的变量为空时,就会返回|右边的值'}}</p> <p>{{ file_size|filesizeformat }} 就相当于是一个转换,把kb转为mb</p> <p>{{ info|truncatewords:3}} 按照空格截取内容的 三个点不算</p> <p>{{ info|truncatechars:9 }}按字符截取内容的 三个点也算 </p> <p>{{ xxx|safe }}前端取消转义 </p> <p>{{ yyy|safe}} 前端取消转义</p> <p>{{ zzz }} 这个在后端取转义了</p> <p>{{ time }}</p> <p>{{ time|date:'Y-m-d' }} 只需要掌握年月日就可以了</p> <p>{{ n|add:100 }} 做数字相加</p> <p>{{ s|add:'大傻叉' }} 做字符串拼接</p> <p>{{ l|slice:'0:3' }}切片取值</p> <p>{{ l|slice:'0:5:2' }}切片取值</p>
后端详细代码:
1 def reg(request): 2 # 以下的数据类型都是可以被传递给前端的 3 n = 0 4 ss = '' 5 f = 1.11 6 s = '你妹的' 7 l = [1, 2, 3, 4, 5] 8 d = {"name": 'jason', 'password': 123} 9 t = (1, 2, 3, 4, 5) 10 se = {1, 2, 3, 4, 5, 6, 7, } 11 file_size = 12312312 12 info = 'my name is zy' 13 xxx = '<h1>呃呃呃呃呃</h1>' 14 yyy = '<script>alert(123)</script>' 15 16 from django.utils.safestring import mark_safe 17 zzz = mark_safe('<h1>你是弱智</h1>') 18 from datetime import datetime 19 time=datetime.now() 20 21 return render(request,'reg.html',locals())
模版语法之标签(逻辑相关):
for 循环执行流程图:
# for 循环 {% for s in l %} <p>{{ forloop }}</p> # forloop可以看到for循环的执行流程 {{ s }} {% endfor %} # if else 判断 对象有值就走true 对象为空就走false {% if '' %} <p>xxx条件为true</p> {% else %} <p>xxx条件为false</p> {% endif %} #for 循环里面可以套if elif else 判断是for循环是否为第一次和最后一次 #如果判断对象为空,就走empty {% for foo in '' %} {% if forloop.first %} <p>这是我的第一次</p> {% elif forloop.last %} <p>这是最后一次了啊</p> {% else %} <p>来啊来啊!!!</p> {% endif %} {% empty %} <p>当for循环的对象为空的时候 会走empty</p> {% endfor %} #django模板语法在取值的时候 统一使用句点符(大白话就是 点号 .) #俩种写法 1. {{l.6.3.name}} 但是这么写,如果多个地方需要取到的值,太麻烦了 2. <p> {% with l.6.3.name as ttt %} 可以给一个比较复杂的取值操作取一个别名 之后在with语句中 就可以使用该别名 {{ ttt }} {% endwith %} </p> # for 循环环也支持循环字典 对象.kyes values items {% 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 %}
后端详细代码:
1 def reg(request): 2 # 以下的数据类型都是可以被传递给前端的 3 n = 0 4 ss = '' 5 f = 1.11 6 s = '你妹的' 7 l = [1,2,3,4,5,6,[12,3,4,{'name':'heiheihei'}]] 8 d = {"name": 'jason', 'password': 123} 9 t = (1, 2, 3, 4, 5) 10 se = {1, 2, 3, 4, 5, 6, 7, } 11 file_size = 12312312 12 info = 'my name is zy' 13 14 15 return render(request,'reg.html',locals())
自定义过滤器的使用:
自定义标签 过滤器 inclusion_tag 自定义固定的三步骤(重点) 1.必须在你的应用下新建一个名为templatetags文件夹 2.在该文件夹内新建一个任意名称的py文件 3.在该py文件中固定先写下面俩句代码 from django import template register = template.Library()
|length
|add
|default
|filesizeformat
|truncatewords
|truncatechars
|safe
|slice
自定义过滤器,自定义标签,自定义inclusion_tag:
后端: # 自定义过滤器 @register.filter(name='baby') def index(a,b): # 这个过滤器只是做一个简单的加法运算 return a + b 前端: {% load mytage %} {{ 123|baby:1 }} 注意: 自定义过滤器 只能由两个形参 但是你可以在给第二个参数传值的时候 传一个字符串 只要思想不滑坡 方法总比困难多 {{ 123|baby:'1|2|3|4|5|6'}}
自定义标签:
后端: # 它可以支持传多个值 @register.simple_tag(name='zy') def zzz(a,b,c,year): return '%s %s %s %s'%(a,b,c,year) 前端: {#支持传多个值,参数与参数之间必须要用空格隔开#} {% load mytage %} {% zy 1 2 3 year=5 %}
自定义inclusion_tag:
当你的页面上有一部分html代码需要经常被各个inclusion_tag地方使用 并且需要传参才能渲染出来 那么你可以把该html代码部分制作成一个inclusion_tag 任何页面都能使用 后端: #自定义inclusion_tag @register.inclusion_tag('bigplus.html') def bigplus(n): l=[] for i in range(n): l.append('第%s项'%i) return {'l':l} 前端bigplus里面: <ul> {% for foo in l %} <li>{{ foo }}</li> {% endfor %} </ul> 前端reg里面: {% load mytag %} {% bigplus 5 %}
模板的继承(重点):
当多个页面整体的样式都大差不差的情况下,可以设置一个模板文件,在该模板文件中,
使用block块划分多个区域,之后其他子版要使用模板的时候,可以通过block块的名字,
来选定到底需要修改那一部分区域。 模板一般情况下,应该至少有三个可以被修改的区域 1. {% block css %} 子页面自己的css代码 {% endblock %} 2. {% block content %} 子页面自己的html代码 {% endblock %} 3. {% block js %} 子页面自己的js代码 {% endblock %}
注意:
一般情况下 模板上的block越多,页面的可扩展性就越强
模板的导入:
模板的导入 {% include 'beautiful.html' %} 当你写了一个特别好看的form表单/列表标签等 可以将它当成一个模块 哪个地方需要 就直接导入使用即可
模型层:
单表操作:
1.单表操作 create_time = models.DateField() 关键性的参数 1.auto_now:每次操作数据 都会自动刷新当前操作的时间 2.auto_now_add:在创建数据的时候 会自动将创建时间记录下来 后续的修改不会影响该字段 ps:在django中 你可以写一个单独测试某一个py文件的测试脚本 不需要再频繁的走web请求
查看orm内部sql语句的方法有哪些 1.如果是queryset对象 那么可以点query直接查看该queryset的内部sql语句 2.在django项目的配置文件中 配置一下参数即可实现所有的orm在查询的时候自动打印对应的sql语句 直接把以下代码拷贝就可以了
1 LOGGING = { 2 'version': 1, 3 'disable_existing_loggers': False, 4 'handlers': { 5 'console':{ 6 'level':'DEBUG', 7 'class':'logging.StreamHandler', 8 }, 9 }, 10 'loggers': { 11 'django.db.backends': { 12 'handlers': ['console'], 13 'propagate': True, 14 'level':'DEBUG', 15 }, 16 } 17 }
必知必会13条:
1.all(): 查询所有的结果 2.filter(**kwargs): 它包含了所给筛选条件相匹配的对象,传入的是字典的格式(**kwargs) 3.get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。 4.exclude(**kwargs): exclude就是取反的意思,拿到除了这个其他所有对象的请求集合 5.values(): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列,values相当于查找某一特定字段的所有值 6.values_list(): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列 7.order_by(): 对查询结果排序 8.reverse(): 对查询结果反向排序,请注意reverse()通常只能在具有已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法)。 9.distinct(): 去重的意思,必须一模一样 10.count(): 返回数据库中匹配查询的对象数量。 11.first(): 返回第一条记录 12.last(): 返回最后一条记录 13.exists(): 如果包含数据,就返回True,否则返回False。没什么用 返回QuerySet对象的方法有: all() filter() exclude() order_by() reverse() distinct() 特殊的QuerySet values() 返回一个可迭代的字典序列 values_list() 返回一个可迭代的元祖序列 返回具体对象的 get() first() last() 返回布尔值的方法有: exists() 返回数字的方法有 count()
增删改查操作详情:
1 import os 2 import sys 3 4 if __name__ == "__main__": 5 # django在启动的时候 就会往全局的大字典中设置一个键值对 值是暴露给用户的配置文件的路径字符串 6 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day54.settings") 7 8 import django 9 django.setup() 10 from app01 import models 11 models.Book.objects.all() 12 # 增 13 # 方式1: create 14 # book_obj = models.Book.objects.create(title='三国',price=19.99,create_time='2019-11-11') 15 # print(book_obj.title) 16 # 方式2:对象点save()方法 17 # from datetime import datetime 18 # ctime = datetime.now() 19 # book_obj = models.Book(title='金瓶',price=96.66,create_time=ctime) 20 # book_obj.save() 21 22 # 查 23 # print(models.Book.objects.all()) 24 # print(models.Book.objects.get(id=1)) 25 # print(models.Book.objects.get(pk=1)) 26 """ 27 pk会自动查找到当前数据的主键字段 28 """ 29 # print(models.Book.objects.filter(pk=2)) 30 31 # 改 32 # 1.update 33 # models.Book.objects.filter(pk=1).update(title='三国演义') 34 # 2.对象.save() 35 # book_obj = models.Book.objects.get(pk=1) 36 # book_obj.price = 666.66 37 # book_obj.save() 38 39 # 删除 delete() 40 # models.Book.objects.filter(pk=2).delete() 41 42 # < 1 > all(): 查询所有结果 43 44 # < 2 > filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 45 # < 3 > get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。(源码就去搂一眼~诠释为何只能是一个对象) 46 # < 4 > exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象 47 # print(models.Book.objects.exclude(pk=1)) # 只要pk不是1的数据全部查询出来 48 49 50 # < 5 > order_by(*field): 对查询结果排序('-id') / ('price') 51 # print(models.Book.objects.order_by('price')) # 默认是升序 52 # print(models.Book.objects.order_by('-price')) # 加负号就是降序 53 54 55 # < 6 > reverse(): 对查询结果反向排序 >> > 前面要先有排序才能反向 56 # print(models.Book.objects.order_by('price').reverse()) 57 58 # < 7 > count(): 返回数据库中匹配查询(QuerySet) 59 # print(models.Book.objects.count()) # 对查询出来的结果进行一个计数 60 61 62 # 的对象数量。 63 # < 8 > first(): 返回第一条记录 64 # print(models.Book.objects.filter(pk=1).first()) 65 # < 9 > last(): 返回最后一条记录 66 # print(models.Book.objects.all()) 67 # print(models.Book.objects.all().last()) 68 69 # < 10 > exists(): 如果QuerySet包含数据,就返回True,否则返回False 70 # print(models.Book.objects.filter(pk=1000)) 71 # print(models.Book.objects.filter(pk=1000).exists()) 72 73 74 # < 11 > values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 75 # model的实例化对象,而是一个可迭代的字典序列 76 # print(models.Book.objects.values('title','price')) # 得到的结果是列表套字典 77 78 79 80 # < 12 > values_list(*field): 它与values() 81 # print(models.Book.objects.values_list('title','price')) # 得到的结果是列表套元组 82 83 84 # 非常相似,它返回的是一个元组序列,values返回的是一个字典序列 85 # < 13 > distinct(): 从返回结果中剔除重复纪录 86 """ 87 去重的前提是 一定要有完全重复的数据 才能去重 88 """ 89 # print(models.Book.objects.filter(title='三国演义').distinct()) 90 # print(models.Book.objects.values('title','price','create_time').distinct())
# FBV