django目前所用整理

git:https://gitee.com/momomoyu/django-js-html

分页器

分页器是基于form提交的,与ajax很难形成动态局部刷新(以目前的水平以及调研程度来讲)

后面更换为了基于handlebar.js和pagination.js的动态局部刷新

关于封包如何存储与static中,可在其中下载得到。

其中handlebars在linux环境下,其内的div设置的flow及col的属性存在冲突,还在纠正问题所在。

models的使用

在本帖中可以看到

https://www.cnblogs.com/threeidiots/articles/14139306.html

简介
查询集表示从数据库中获取的对象集合
查询集可以含有零个、一个或多个过滤器
过滤器基于所给的参数限制查询的结果
从Sql的角度,查询集和select语句等价,过滤器像where和limit子句
接下来主要讨论如下知识点
查询集
字段查询:比较运算符,F对象,Q对象
查询集
在管理器上调用过滤器方法会返回查询集
查询集经过过滤器筛选后返回新的查询集,因此可以写成链式过滤
惰性执行:创建查询集不会带来任何数据库的访问,直到调用数据时,才会访问数据库
返回查询集的方法,称为过滤器
all()
filter()
exclude()
order_by()
values():一个对象构成一个字典,然后构成一个列表返回
写法:
filter(键1=值1,键2=值2)
等价于
filter(键1=值1).filter(键2=值2)
返回单个值的方法
get():返回单个满足条件的对象
如果未找到会引发"模型类.DoesNotExist"异常
如果多条被返回,会引发"模型类.MultipleObjectsReturned"异常
count():返回当前查询的总条数
first():返回第一个对象
last():返回最后一个对象
exists():判断查询集中是否有数据,如果有则返回True
限制查询集
查询集返回列表,可以使用下标的方式进行限制,等同于sql中的limit和offset子句
注意:不支持负数索引
使用下标后返回一个新的查询集,不会立即执行查询
如果获取一个对象,直接使用[0],等同于[0:1].get(),但是如果没有数据,[0]引发IndexError异常,[0:1].get()引发DoesNotExist异常
查询集的缓存
每个查询集都包含一个缓存来最小化对数据库的访问
在新建的查询集中,缓存为空,首次对查询集求值时,会发生数据库查询,django会将查询的结果存在查询集的缓存中,并返回请求的结果,接下来对查询集求值将重用缓存的结果
情况一:这构成了两个查询集,无法重用缓存,每次查询都会与数据库进行一次交互,增加了数据库的负载
print([e.title for e in Entry.objects.all()])
print([e.title for e in Entry.objects.all()])
情况二:两次循环使用同一个查询集,第二次使用缓存中的数据
querylist=Entry.objects.all()
print([e.title for e in querylist])
print([e.title for e in querylist])
何时查询集不会被缓存:当只对查询集的部分进行求值时会检查缓存,但是如果这部分不在缓存中,那么接下来查询返回的记录将不会被缓存,这意味着使用索引来限制查询集将不会填充缓存,如果这部分数据已经被缓存,则直接使用缓存中的数据
字段查询
实现where子名,作为方法filter()、exclude()、get()的参数
语法:属性名称__比较运算符=值
表示两个下划线,左侧是属性名称,右侧是比较类型
对于外键,使用“属性名_id”表示外键的原始值
转义:like语句中使用了%与,匹配数据中的%与,在过滤器中直接写,例如:filter(title__contains="%")=>where title like ‘%%%’,表示查找标题中包含%的
比较运算符

exact:表示判等,大小写敏感;如果没有写“ 比较运算符”,表示判等
filter(isDelete=False)
contains:是否包含,大小写敏感
exclude(btitle__contains=‘传’)
startswith、endswith:以value开头或结尾,大小写敏感
exclude(btitle__endswith=‘传’)
isnull、isnotnull:是否为null
filter(btitle__isnull=False)
在前面加个i表示不区分大小写,如iexact、icontains、istarswith、iendswith
in:是否包含在范围内
filter(pk__in=[1, 2, 3, 4, 5])
gt、gte、lt、lte:大于、大于等于、小于、小于等于
filter(id__gt=3)
year、month、day、week_day、hour、minute、second:对日期间类型的属性进行运算
filter(bpub_date__year=1980)
filter(bpub_date__gt=date(1980, 12, 31))
跨关联关系的查询:处理join查询
语法:模型类名 <属性名> <比较>
注:可以没有__<比较>部分,表示等于,结果同inner join
可返向使用,即在关联的两个模型中都可以使用
filter(heroinfo_ hcontent contains=‘八’)
查询的快捷方式:pk,pk表示primary key,默认的主键是id
filter(pk__lt=6)
聚合函数
使用aggregate()函数返回聚合函数的值
函数:Avg,Count,Max,Min,Sum
from django.db.models import Max
maxDate = list.aggregate(Max(‘bpub_date’))
count的一般用法:
count = list.count()
F对象
可以使用模型的字段A与字段B进行比较,如果A写在了等号的左边,则B出现在等号的右边,需要通过F对象构造
list.filter(bread__gte=F(‘bcommet’))
django支持对F()对象使用算数运算
list.filter(bread__gte=F(‘bcommet’) * 2)
F()对象中还可以写作“模型类__列名”进行关联查询
list.filter(isDelete=F(‘heroinfo__isDelete’))
对于date/time字段,可与timedelta()进行运算
list.filter(bpub_date__lt=F(‘bpub_date’) + timedelta(days=1))
Q对象
过滤器的方法中关键字参数查询,会合并为And进行
需要进行or查询,使用Q()对象
Q对象(django.db.models.Q)用于封装一组关键字参数,这些关键字参数与“比较运算符”中的相同
from django.db.models import Q
list.filter(Q(pk lt=6))
Q对象可以使用&(and)、|(or)操作符组合起来
当操作符应用在两个Q对象时,会产生一个新的Q对象
list.filter(pk lt=6).filter(bcommet gt=10)
list.filter(Q(pk lt=6) | Q(bcommet _gt=10))
使用~(not)操作符在Q对象前表示取反
list.filter(~Q(pk__lt=6))
可以使用&|~结合括号进行分组,构造做生意复杂的Q对象
过滤器函数可以传递一个或多个Q对象作为位置参数,如果有多个Q对象,这些参数的逻辑为and
过滤器函数可以混合使用Q对象和关键字参数,所有参数都将and在一起,Q对象必须位于关键字参数的前面

转载自传智播客

关键在于惰性查询和缓存部分,这部分没有多余的佐证,目前的理解就是在当前函数内,存在第二次缓存。退出函数之后缓存失效。其余部分可作为工具书参考。

queryset整理

特性:可迭代,可切片,惰性,缓存

queryset为models查询出的结果集,最外侧是列表,每一条都是一个字典,携带表名,pk(id)以及fields(其他属性)等,fields里面承载的数据。

在创建时不会进行查询操作,只有在使用过滤器时会触发查询,然后缓存。缓存机制在models中有所论述。

queryset虽然可以通过for循环进行遍历,但是其每一条并不等同于字典,直接通过[]进行访问会报迭代错误。其每一条可通过.进行访问,

T = NightResult.objects.all()[:1] 
print(T[0].result)
for i in T:
   i.id

queryset可以切片查询,但是不支持负索引,切片查询时会只查询指定范围。

另外queryset可以更新单条,但是与update不同,update会直接递交数据库,但是对于queryset而言,不主动递交,是不会将本地的修改递交到数据库的。

twz = Author.objects.get(name="WeizhongTu")
twz.name="WeizhongTu"
twz.email="tuweizhong@163.com"
twz.save()  # 最后不要忘了保存!!!

queryset创建对象的方法

#总之,一共有四种方法
# 方法 1
Author.objects.create(name="WeizhongTu", email="tuweizhong@163.com")
 
# 方法 2
twz = Author(name="WeizhongTu", email="tuweizhong@163.com")
twz.save()
 
# 方法 3
twz = Author()
twz.name="WeizhongTu"
twz.email="tuweizhong@163.com"
twz.save()
 
# 方法 4,首先尝试获取,不存在就创建,可以防止重复
Author.objects.get_or_create(name="WeizhongTu", email="tuweizhong@163.com")
# 返回值(object, True/False)

前三种返回object,最后一种多返回一个bool值。

.distinct()可进行去重,在查询列名时可以使用,联表查询时也可以使用

 queryset对于惰性的解释:

官方文档

概括:

query在被构造,切片等操作时不会对数据库操作, 这里就是queryset惰性, 也叫惰性查询,也就是说单纯的创建queryset

那么, 什么操作会使queryset进行数据库活动呢:

迭代(Iteration), for i in queryset
切片(Slicing), 带有步长的切片, queryset[::2]
索引, queryset[0]
序列化/缓存化(Pickling/Caching), 将数据保存到redis中或者内存中的时候
repr(). 直接打印, print(queryset)
len(). len(queryset)
list(). list(queryset)
bool(). queryset if queryset else None
queryset关于缓存的机制

每个查询集都包含一个缓存来最小化对数据库的访问。理解它是如何工作的将让你编写最高效的代码。

在一个新建的查询集中,缓存为空,首次对查询集求值,会发生数据库查询,django会将查询的结果保存到缓存中并返回明确的请求结果,接下来的求值将复用缓存的结果。

对查询集使用不当的话,它会浪费系统资源。例如,下面的语句创建两个查询集,对它们求值,然后扔掉它们:

print([a.title for a in models.Article.objects.all()])
print([a.create_time for a in models.Article.objects.all()])

如此,相同的查询会被调用两次,致使数据库负载增大,但是这个地方还是有一定疑问的,它是如何保证查询集的最新状态呢?

何时查询集不会被缓存?

查询集不会永远缓存他们的结果,当只对查询集的部分进行求值时会检查缓存,如果这个部分不在缓存中,name接下来查询返回的结果都不会被缓存,所以,切片或索引来限制查询集将不会填充缓存。

例如,重复获取查询集对象中一个特定的索引将每次都查询数据库

>>> queryset = Entry.objects.all()
>>> print queryset[5] # Queries the database
>>> print queryset[5] # Queries the database again

然而,如果已经对全部查询集求值过,则将检查缓存:

>>> queryset = Entry.objects.all()
>>> [entry for entry in queryset] # Queries the database
>>> print queryset[5] # Uses cache
>>> print queryset[5] # Uses cache

下面的一些其他栗子,他们会是的全部的查询集被求值并填充到缓存:

>>> [entry for entry in queryset]
>>> bool(queryset)
>>> entry in queryset
>>> list(queryset)

简单的打印查询集不会填充缓存。

exists()与iterator()方法:

简单的使用if语句进行判断也会执行查询并将整个数据放入cache,虽然我们并不需要这些数据,为防止这种情况,可以用exists()来检查是否有数据:

 if queryResult.exists():
    #SELECT (1) AS "a" FROM "blog_article" LIMIT 1; args=()
        print("exists...")

而iterator可以在查询集太大时,不保留缓存,因为太大的数据存入缓存是不够高效的,巨大的数据量进行缓存可能锁住系统进程,让程序濒临崩溃,为避免在遍历数据时产生queryset cache,可以使用iterator()来获取数据,处理完数据后将其丢弃。

objs = Book.objects.all().iterator()
# iterator()可以一次只从数据库获取少量数据,这样可以节省内存
for obj in objs:
    print(obj.title)
#BUT,再次遍历没有打印,因为迭代器已经在上一次遍历(next)到最后一次了,没得遍历了
for obj in objs:
    print(obj.title)

iterator的使用环境是为了防止生成cache,同时会产生遍历同一个queryset是会重复执行查询的问题,所以使用之前需要确保在操作一个大的queryset是没有执行重复查询。

总结:

queryset的cache可以用于减少程序对数据库的查询,通常使用下会保证只有在需要的时候才会查询数据库,使用exists和iterator方法时可以优化程序对内存的使用,但是可能会造成额外的数据库查询,

posted @ 2021-04-13 15:18  idiots  阅读(65)  评论(0编辑  收藏  举报