day07自定义过滤器、标签、inclusion_tag、模板的继承与导、入双下划线查询
昨日内容复习
-
三板斧
HttpResponse render redirect 视图函数必须返回一个HttpResponse对象
-
JsonResponse
from django.http import JsonResponse #看源码得出来的结论 JsonResponse(要序列化的变量名,json_dumps_parm={指定一个字典比如 ensure_ascii=False 中文直接显示 不让他转码},safe=False 非字典对象序列化这个参数设置为False就ok了)
-
from表单传文件
首先必须是Post 然后必须指定entype='multipart/form-data' 才可以传输文件类对象 前端还可以指定<input type="file" name="file" multiple> 一次性获取多个 后端接受 文件类型:request.Post 普通文本类型:request.Files request.Files.get()获取文件对象单个 request.Files.getlist()获取文件对象多个
-
FBV和CBV
FBV:基于函数的视图 from app01 import views 路由:url(r'^index/',视图函数名) CBV:基于类的视图 from django.views import View 路由:url(r'^login/',views.类名.as_view()) 视图层 from django.views import View class Mylogin(View): def get(self,request): return HttpResponse('get请求') def post(self,request): return HttpResponse('post请求') ''' 口述CBV过程 发现了路由层调用一个函数 这个函数是哪的 因为是类调用直接去类找,没,去他的父类中找找到了, as_view retrun了 view这个函数 view这个函数 定义了一个类的对象 return了 对象的dispatch方法 这个方法对象 没有 类没有 父类有 这个方法把请求的方法转小写并判断是否在八个默认方法里面 在利用反射获取对象中具有与请求方法相同的方法名 内存地址赋值给handler 不在返回一个报错方法 最终执行这个handler并return 然后return 对象名()调用 '''
-
模板语法传值
所有数据对象都能传过去 render从后端传过去 可以字典传输 也可以locals全部传送 前端只能用句点符取值 就是点的方式 {{}} # 跟变量名相关 {%%} # 跟功能逻辑相关 for if
-
模板语法之过滤器
{{ 数据对象|过滤器名称:参数}} |length #长度 |add:参数 #添加 |default:false执行的 # 默认值 前面是 |date:'Y-m-d H:i:s' # 日期格式 |truncatewords:3 #按照单词截取不包括那三个点 |truncatechars:10 #按照字符截取 包括三个点的位置 |filesizeformat #统计大小 k kb等 |safe #转义 后端的html 或者js等直接执行 不会返回字符串给前端 #学习了该方法之后要有一个认识:html里面的代码不一定非要在html文件中编写 也可以在后端编写好了之后传递给前端 后端也可以提前转义 from django.utils.safe_string import mark_safe res = mark_safe('<h1>123</h1>')
-
模板语法之标签
{% for foo in s %} {% if forloop.first %} #第一次循环执行这个 <p>这是第一次循环</p> {% elif forloop.last %} #最后一次循环执行这个 <p>这是最后一次</p> {% else %} <p>继续!!!</p> {% endif %} {% empty %} forloop 里面的参数 count0 从索引o开始 count 从索引1开始 revcounter 倒序 一直到索引1 revcounter0 倒序 一直到索引0 first 第一个为true 其他为false last 最后一个为true 其他为false {% for i in data_list %} {{ forloop }} # first last counter0 counter {% empty %} # for循环对象内部没有值的情况下执行的代码 {% endfor %}
今日内容概要
-
自定义过滤器、标签、inclusion_tag(BBS作业用一次)
-
模板的继承(django前后端结合 那么使用频率较高)
-
模板的导入(类似于python中导入模块)
-
模型层(ORM语句)
-
图书管理系统表设计
-
ORM之神奇的双下划綫查询
今日内容详细
自定义义过滤器、标签、inclusion_tag (了解即可)
过滤器相当于python中的内置函数 自定义过滤器相当于python中自定义函数
自定义标签也是自定义函数
"""
自定义过滤器 标签 inclusion_tag都需要三步走战略
1.在应用文件夹(app)下创建一个名字必须叫templatetags文件夹
2.在创建的文件夹下创建一个任意名称的py文件 比如mytag
3.在该py文件内先固定写两句话
from django import template
register = template.Library()
自定义过滤器:在html页面调用这个过滤器名称 他去自定义的过滤器找对应的函数 把函数返回值丢到调这个过滤器的html页面,最多只能传两个参数
自定义标签;在html页面调用这个标签名称 他去自定义的标签找对应的函数 把函数返回值丢到调这个标签的html页面
inclusion_tag:在html页面调用这个,也会去找对应的函数 但是他的返回值放在一个html页面(导航条 from表单等等,不是一个完整的页面),这个小页面塞到调这个的位置上
"""
在自定义的mytag.py里面创建
# 自定义过滤器(无论是内置的还是自定义都只能最多两个参数)
@register.filter(name='gailun')
def add(a, b):
return a + b
# 自定义标签
@register.simple_tag(name='nuoke')
def output(a,b,c,d):
return '%s-%s-%s-%s' %(a,b,c,d)
# 自定义inclusion_tag
@register.inclusion_tag('myul.html',name='my_ul')
def aaa(n):
obj_list=[]
for i in range(1,n+1):
obj_list.append(i)
return locals()
"""
html页面
{% load lol %} 一定要先加载才能使用
{{ s|gailun:111 }} #指定过滤器的名字
{% nuoke 1 2 3 4 %} #调用标签时记得 参数不要加逗号
{% my_ul 10 %} #不要加: ,
"""
模板的继承
在母版中先使用block划定将来可以修改的区域
{% block 自定义名称 %}
母版内容
{% endblock %}
在子版中继承并修改指定区域
{% extends 'home.html' %}
{% block 自定义名称 %}
自定义其他内容
{{ block.super }} # 也可以引用母版的内容
{% endblock %}
"""
母版中最少应该有三块区域
{% block content %} 可以根据页面内容的布局写多个
{% endblock %}
{% block css %} #css 样式的
{% endblock %}
{% block js %} #js样式
{% endblock %}
"""
#login
{% extends 'home.html' %}
{% block css %}
<style>
h1{
color: red;
}
</style>
{% endblock %}
{% block content %}
<h1 class="text-center">Hey men!!</h1>
<p class="text-center">welcome to register !!!!</p>
<form action="">
<p>username:
<input type="text" class="form-control">
</p>
<p>username:
<input type="text" class="form-control">
</p>
<input type="submit" class="btn btn-danger btn-block" value="提交注册">
</form>
{% endblock %}
{% block title %}
注册
{% endblock %}
{% block js %}
<script>confirm('qqqqqqqqq')</script>
{% endblock %}
模板的导入
类似于导模块
该模板不应该是一个完整的页面 而是一个局部页面
很多地方都需要使用的情况下可以使用模板的导入
{% include 'menu.html' %}
模型层(跟数据有关的都是核心)
#django自带的sqlite数据库功能非常的少 并且对日期格式不兼容
1.需要会mysql配置 databases 还有__init__里面配置
2.数据库迁移命令 (分正向反向)
正向 python3 manage.py makemigrations
python3 manage.py migrate
反向 python3 manage.py inspectdb > app名称/models.py 或者
python manage.py inspectdb
3.models 创建表相关操作
charfield(对应sql varchar)记得指定max_length 大小
DecimalField (对应sql decimal ) 记得指定 max_digits=总长度 decimal_places=小数点后面长度
IntegerField (对应sql int)
DateField 日期格式 年月日 auto_now:True自动更新当前时间(每次修改数据都会将时间自动更新) auto_now_add:True自动更新当前时间(创建巨鹿时将时间自动更新 比如图书购买时间)
DateTimeField 日期格式 年月日 时分秒
测试环境
1.python console
2.py文件形式(参考manage.py前四行)
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "d19_dj6.settings")
import django
django.setup()
#还需要导入models模块
# 在该代码的下方才可以正常测试django文件
查询关键字
# 查
#在类里加一个__str__(print输出对象时候执行此方法)
def __str__(self):
return self.title
# 1.all()
# res = models.Books.objects.all() # QuerySet res=列表套数据对象
# print(res) 所有数据对象
# print(res.first()) #第一个数据对象
# print(res.last()) #最后一个数据对象
# print(res[1]) #索引1的数据对象
'''queryset支持正数的索引取值'''
# print(res)
# 2.filter()
# res = models.Books.objects.filter(id=1) QuerySet
'''pk能够自动定位当前表的主键字段 避免了你自己去频繁查看'''
# res = models.Books.objects.filter(pk=2) QuerySet id=2的数据对象
# print(res)
'''filter括号内可以存放多个条件默认是and关系'''
# res = models.Books.objects.filter(pk=2,title='jpm')
# print(res)
# 3.values()
'''values可以指定查询的字段 结果QuerySet 列表套字典'''
# res = models.Books.objects.values('title','price')
# 4.values_list()
'''values_list也可以指定查询的字段 结果QuerySet 列表套元组'''
# res = models.Books.objects.values_list('title', 'price')
# print(res)
# 5.first()与last() 分别获取queryset第一个和最后一个数据对象
#下面这个先获取全部数据对象 where没条件 然后获取title和price字段
# res = models.Books.objects.all().filter().values('title','price')
# print(res)
'''只要是queryset对象 就可以无限制的调用queryset对象的方法'''
# 6.get() 不推荐使用
# res = models.Books.objects.get(pk=1)
'''get方法可以直接获取到数据对象'''
# print(res,res.pk,res.title,res.price,res.publish_time)
'''但是该方法当查询条件不存在的时候会直接报错 没有filter好用!!!'''
# res = models.Books.objects.get(pk=100) #报错
# res1 = models.Books.objects.filter(pk=100) #返回一个空的queryset
# print(res1)
# 7.exclude() 取反 QuerySet 列表套数据对象
# res = models.Books.objects.exclude(pk=1) #查找主键值不是1的 数据对象
# print(res)
# 8.order_by() 排序 QuerySet 列表套数据对象
# res = models.Books.objects.order_by('price') #默认升序
# res1 = models.Books.objects.order_by('-price') #查询的字段前面加一个- 实现了降序
# print(res)
# 9.reverse() 翻转(必须提前有顺序才可以) 挺鸡肋的 先排序在降序 直接上面那个价格-就ok了
# res = models.Books.objects.all()
# print(res)
# print(res.order_by('price'))
# print(res.order_by('price').reverse())
# 10.distinct() 去重
'''尤其要注意主键字段''' 主键绝对不会一样
# res = models.Books.objects.all()
# print(res)
# print(res.distinct())
# 11.count() 计数
# res = models.Books.objects.all().count()
# res1 = models.Books.objects.count()
# print(res, res1) # 4 4
# 12.exists() 判断结果集是否有数据(不需要使用)
# res = models.Books.objects.all().exists()
# res1 = models.Books.objects.filter(id=100).exists()
# print(res,res1) # True False
# 13.create()、update()、delete()、对象.save()
如何查看SQL语句
1.如果当前对象是queryset那么可以直接点query查找该对象内部SQL语句
2.配置文件(只要执行orm语句都会自动打印SQL语句)
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
神奇的双下划线查询
# 神奇双下划綫查询
# 1.查询价格大于800的书籍
# res = models.Books.objects.filter(price__gt=800)
# print(res)
# 2.查询价格小于800的书籍
# res = models.Books.objects.filter(price__lt=800)
# print(res)
# 3.查询价格大于等于800的书籍
# res = models.Books.objects.filter(price__gte=800)
# print(res)
# 4.查询价格小于等于800的书籍
# res = models.Books.objects.filter(price__lte=800)
# print(res)
# 5.查询价格是989.45 或者278.89 或者888.21
# res = models.Books.objects.filter(price__in=["888.21","278.89","989.45"])
# print(res)
# 6.查询价格在200到800之间的书籍
# res = models.Books.objects.filter(price__range=(200,800))
# print(res)
# 7.查询书籍名称中包含字母p的书(区分大小写)
# res = models.Books.objects.filter(title__contains='p')
# print(res)
# res = models.Books.objects.filter(title__icontains='p')
# print(res)
# 8.查询书籍是否以...开头 ...结尾
# res = models.Books.objects.filter(title__startswith=)
# res1 = models.Books.objects.filter(title__endswith=)
# 9.查询出版日期是2021的书(常用)
res = models.Books.objects.filter(publish_time__year=2021)
res1 = models.Books.objects.filter(publish_time__month=11)
print(res,res1)
#统计
字段名__gt=值 某个字段大于某个值的数据对象
字段名__gte=值 某个字段大于等于某个值的数据对象
字段名__lt=值 某个字段小于某个值的数据对象
字段名__lte=值 某个字段小于等于某个值的数据对象
字段名__in=['123','234'] 某个字段等于值1或值2或值3 的数据对象
加引号看前提 ,如果是浮点型要加引号,因为python对浮点数这块不够精确
字段名__range=(200,500) 某个字段的值在200-500之间 的数据对象
字段名__contains='p' 某个字段的值包含字母'p'之间 的数据对象 区分大小写
字段名__icontains='p' 某个字段的值包含字母'p'之间 的数据对象 不区分大小写
字段名__startswith='人' 某个字段以'人'开头的数据对象
字段名__ebdswith='的' 某个字段以'的'结束的数据对象
#前提是日期类型
字段名__year=2021 某个字段的年份为'2021'的数据对象
字段名__month=11 某个字段的月为'11'的数据对象
图书管理系统表设计
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8, decimal_places=2)
publish_time = models.DateField(auto_now_add=True)
publish = models.ForeignKey(to='Publish')
authors = models.ManyToManyField(to='Author')
class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=64)
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
author_detail = models.OneToOneField(to='AuthorDetail')
class AuthorDetail(models.Model):
phone = models.BigIntegerField()
addr = models.CharField(max_length=32)