目录

常用13招 + 2

十三式

测试的models

class City(models.Model):
name= models.CharField(max_length=30)
# def __str__(self):
# return class Meta:
ordering = ("id",)
# unique_together = ("name","phone")

( 1 )  filter有过滤功能,没有则返回None

models.Tb1.objects.filter(条件)

( 2 )  get如果没有则会报错,因此一般会用filter进行查询

models.Tb1.objects.all.get(条件,None)    # 字典查询,如果没有就赋值为None,防止报错

( 3 )  exclude( 条件 ),相当于 not in 条件

models.Tb1.objects.exclude(id__in=[11, 22, 33])       # not  in [ 11,33,22]

( 4 )  values(字段名字):返回的是[{key:v},{k,v}],因此取值先列表后字典取值


------------------------------
<QuerySet [{'name': '上海'}, {'name': '北京'}, {'name': '广州'}, {'name': '深圳'}, {'name': '南宁'}]>
上海 在views中
city_list = models.City.objects.filter().values("name")
print(city_list)
print([0]["name"])
return render(request,"en.html",{"city_list":city_list}) html 中取值是
{{ city_list.0.name }}

( 5 )  values_list(*field): 返回的是列表套元祖格式

views中
def a(request,):
city_list = models.City.objects.filter().values_list("name")
print(city_list)
return render(request,"en.html",{"city_list":city_list})
------------------------------
结果是:
[('上海',), ('北京',), ('广州',), ('深圳',), ('南宁',)]> html 中取值
{{ city_list.0.0 }}

( 6 )  order_by(*field):对结果进行排列,


对对象进行排序
def a(request,):
city_list = models.City.objects.filter().order_by("name")
print(city_list)
return render(request,"en.html",{"city_list":city_list})
-------------------
结果是:
<QuerySet [><City: City object (1)>, <City: City object (5)>, <City: City object (3)>>
注意对对象的排序时根据__str__返回值进行排序的,要是在models中设置没有返回值则会报错 def a(request,):
city_list = models.City.objects.filter().values_list("name")
city_list1 = city_list.order_by("name")
print(city_list,city_list1)
return render(request,"en.html",{"city_list":city_list})
---------------------------------
结果分别是:
<QuerySet [('上海',), ('北京',), ('广州',), ('深圳',), ('南宁',)]>
<QuerySet [('上海',), ('北京',), ('南宁',), ('广州',), ('深圳',)]> 在html中对对象取值方式是
{{ city_list.name }}

( 7 )  reverse(): 对已经设置排列方式的结果反向排序,设置排列方式有(在model类的Meta中指定ordering或调用order_by()方法)。

在类中设置
class Person(models.Model):
class Meta:
ordering = ("id",) #切记后面必须有逗号,即是元祖的形式 类中没有设置,则在查询中设置,
def a(request,):
city_list = models.City.objects.filter().order_by("name").reverse()
print(city_list[0])
return render(request,"en.html",{"city_list":city_list}) 在HTML中取值
{% for city in city_list %}
{{ city.name}}
{% endfor %}

( 8 )  distinct():从返回结果中剔除重复纪录(如果你查询跨越多个表,可能在计算QuerySet时得到重复的结果。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重。)

pass

( 9 )   count(): 返回数据库中匹配查询(QuerySet)的对象数量。

pass

( 10 )  first(): 返回第一条记录

pass

( 11 )  last( ) 返回最后一个结果

pass

( 12 )   exists(): 判断返回数据是否为空,就返回True,否则返回False

pass

( 13 )  all(): 查询所有结果

pass

2式(针对外键查询优化)

select_related和prefetch_related

  对于一对一字段(OneToOneField)和外键字段(ForeignKey),可以使用select_related 来对QuerySet进行优化。从正向查询.

  Django >= 1.7,链式调用的select_related相当于使用可变长参数。Django < 1.7,链式调用会导致前边的select_related失效,只保留最后一个。

article = models.Article.objects.select_related("category").select_related("articledetail").get(nid=1)

  使用SQL的JOIN语句进行优化,通过减少SQL查询的次数来进行优化、提高性能。

prefetch_related

  对于多对多字段(ManyToManyField)和一对多字段,可以使用prefetch_related()来进行优化。

  但是对于多对多关系,和外键表查主键表.使用SQL语句解决就显得有些不太明智,因为JOIN得到的表将会很长,会导致SQL语句运行时间的增加和内存占用的增加。分别查询每个表,然后用Python处理他们之间的关系。

b是city的多对多外键
models.City.objects.prefetch_related("b").filter(id=7).values_list("b__name") Province是City的外键表
models.Province.objects.prefetch_related("City").filter(id=5).values_list("City__name")

一张表的主键不可能重复存在,只有在第三张表才会存在重复的id,这样才会节省空间,而做为外键的的id是数字可以重复存在,因此,foreignkey就是多对一的关系,反过来就是一对多关系

查询返回值类型

prefetch_related主要是针对连表过长的外键表进行查询

返回queryset的方法有

queryset定义:

  其就是一个对象集合,并没有到数据库查询,只有当我们要去表中具体数据的时候,他才会去数据库查询,这样就减少了查找数据库次数,提高性能

1 post = Post.objects.all()#返回一个QuerySet对象并赋值给posts

2 available_posts = Posts.filter(status=1)#继续返回一个QuerySet对象并赋值给available_posts

4 print(available_posts)#此时会根据上边的两个条件执行数据查询操作,对应的SQL语句为:SELECT * FROM blog_post where status =1;

返回queryset的方法有

  ( 1 )  all()

  ( 2 )  filter()

  ( 3 )  exclude()

  ( 4 )  order_by()

  ( 5 )  reverse()

  ( 6 )  distinct()

返回特殊的queryset方法有

方法 返回值
alues() 返回列表套字典
values_list() 返回一个列表套元祖

返回具体对象

方法
get()
first()
first()

条件

不等式查询

符号 意义 简写
id__gt 大于 greater than
id__lt 小于 less than
id__in
filter(id__in=[11, 22, 33]) in [ ]
exclude(id__in=[11, 22, 33]) not in [ ]
id__range=[1, 3] 在[1,2,3],区间查找 bettwen and
models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值

models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in models.Tb1.objects.filter(id__range=[1, 3]) # id范围是1到3的,等价于SQL的bettwen and

关键字查询

符号 意义 简写
name__contains="ven" 含有
name__icontains="ven" 含有,大小写不敏感
name__startswith, 以什么开头
name__istartswith, 不区分大小写
name__endswith, 以什么结尾i
name__iendswith 不区分大小写
models.Tb1.objects.filter(name__contains="ven")  # 获取name字段包含"ven"的
models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感

时间查询

models.Class.objects.filter(first_day__year=2017)

数字没有0开头该怎么查询年月. 缺点是查询不到30天的,其不包含30

a= "2019-06"
a,b=a.split("-")
a = int(a)
b = int(b)
start = datetime.date(a, b, 1)
end = datetime.date(a, b, 30)
print(type(a),b)
article_list = models.Article.objects.filter(create_time__gte=start, create_time__lte=end)

1、gt:大于某个时间
now =
datetime.datetime.now()
#前一天
start = now – datetime.timedelta(hours=23, minutes=59, seconds=59)
a=yourobject.objects
.filter(youdatetimcolumn__gt=start)

2、gte:大于等于某个时间:
a=yourobject.objects .filter(youdatetimcolumn__gte=start)

3、lt:小于
a=yourobject.objects .filter(youdatetimcolumn__lt=start)

4、lte:小于等于
a=yourobject.objects .filter(youdatetimcolumn__lte=start)

5、range:查询时间段
start_date = datetime.date(2005, 1, 1)
end_date =
datetime.date(2005, 3, 31)
Entry.objects.filter(pub_date__range=(start_date, end_date))

6、year:查询某年
Entry.objects.filter(pub_date__year=2005)

7、month:查询某月
Entry.objects.filter(pub_date__month=12)

8、day:某天
Entry.objects.filter(pub_date__day=3)

9、week_day:星期几
Entry.objects.filter(pub_date__week_day=2)

10、获取今天的日期,日期格式为yyyy-MM-dd

from django.utils.timezone import now, timedelta
date = now().date() + timedelta(days=-1) #昨天
date = now().date() + timedelta(days=0) #今天
date = now().date() + timedelta(days=1) #明天

注意查询某年某月用大于或者小于结合即可,但是有可能报错,因为月份不一样,一个月多少天也不一样,当设置日期大于本月数,就会抛出异常,查询就需要,多个条件判断,一般和datetime.timedelta(day=1)结合使用

格式是 字段名__条件

跨表查询

直接通过 外键名__外建表字段名__外键---- 其可以进行多次跨表查询

models.City.objects.filter(id=6).values_list("b__name")

------------------------
结果如下:
<QuerySet [('秦时明月汉时关之君临天下',), ('小明hkhkkkhkhk',)]>

跨表计数

models.RegForm.objects.annotate(count=Count("City__id")).values_list("count","name")   #计算个数
models.City.objects.annotate(count=Count("b")).values("b").values("name")

组合和聚合()

主要目的是计算Avg, Sum, Max, Min, Count

聚合和组合用法区别

聚合
.aggregate(Avg("price"), Max("price"), Min("price")) 组合
.annotate(avg=Avg("salary").values(dept, "avg")

聚合查询(单表)

其作用是对某一字段进行组合求平均值,像group_by一样,对数字敏感

from django.db.models import Avg, Sum, Max, Min, Count

models.Book.objects.all().aggregate(Avg("price"), Max("price"), Min("price"))
-----------------------------------
结果是:
{'price__avg': 13.233333, 'price__max': Decimal('19.90'), 'price__min': Decimal('9.90')}

组合查询(相当于group_by)

组合主要目的是计算Avg, Sum, Max, Min, Count

如计算一本书的作者数量

models.Book.objects.annotate(count=Count("author"))

以author字段组合,提取作者字段,再提取作者表中name字段

models.Book.objects.values(author).annotate(count=Count("price"))

annotate(count=Count("price"))前面是什么以以什么为组合依据,直接取值就可以,不用跨表

一本书的作者是,直接用跨表查询即可

print(models.Book.objects.filter(id=6).values_list("author__name"))

F查询(字段对比)

两字段大小筛选

查询评论数大于收藏数的书籍

from django.db.models import F
models.Book.objects.filter(commnet_num__gt=F('keep_num'))

Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。

models.Book.objects.filter(commnet_num__lt=F('keep_num')*2)

修改操作也可以使用F函数,比如将每一本书的价格提高30元

models.Book.objects.all().update(price=F("price")+30)

某字段值后面添加内容

如:把所有书名后面加上(第一版)

from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.all().update(title=Concat(F("title"), Value("("), Value("第一版"), Value(")"))) 追加) ( 第一版 ) #value可以是多个,相当于拼接

与或查询

与查询

与条件查询非常简单,条件之间直接用逗号隔开即可

models.City.objects.filter(name__endswith="以",name__contains='钱')

Q中的与或非查询

或查询的格式 :把条件放在Q里面,或条件用| 隔开

models.Book.objects.filter(Q(authors__name="小仙女")|Q(authors__name="小魔女"))

非条件查询格式是: 把条件放在Q里面,或条件用~ 隔开,如查找name属性不包含有小仙女的对象,与条件查询直接用 &(在有Q情况下) 隔开即可,也可以逗号隔开,如查询作者名字是小仙女并且不是2018年出版的书的书名。

models.Book.objects.filter(Q(author__name="小仙女") & ~Q(publish_date__year=2018)).values_list("title")

查询出版年份是2017或2018,书名中带物语的所有书。

models.Book.objects.filter(Q(publish_date__year=2018) | Q(publish_date__year=2017), title__icontains="物语")

事务操作

主要是导入事务模块,把想要执行事务操作语句放在放在其中就可以了,最后用try包起来,防止报错

import os
from django.db import transaction if __name__ == '__main__':
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
import django
django.setup() import datetime
from app01 import models try: with transaction.atomic():
new_publisher = models.Publisher.objects.create(name="火星出版社")
models.Book.objects.create(title="橘子物语", publish_date=datetime.date.today(), publisher_id=10) # 指定一个不存在的出版社id
except Exception as e:
print(str(e))

不常用的查询

自写sql查询

终端打印sql语句

在setting配置一下文件即可

LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}

脚本导入项目环境

import os

if __name__ == '__main__':
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
import django
django.setup() from app01 import models books = models.Book.objects.all()
print(books)

切记要先导入环境,才能导入项目模块

 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
import django
django.setup()

select_related和prefetch_related

查询方法大全

def all(self)
# 获取所有的数据对象 def filter(self, *args, **kwargs)
# 条件查询
# 条件可以是:参数,字典,Q def exclude(self, *args, **kwargs)
# 条件查询
# 条件可以是:参数,字典,Q def annotate(self, *args, **kwargs)
# 用于实现聚合group by查询 from django.db.models import Count, Avg, Max, Min, Sum v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id'))
# SELECT u_id, COUNT(ui) AS `uid` FROM UserInfo GROUP BY u_id v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id')).filter(uid__gt=1)
# SELECT u_id, COUNT(ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1 v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id',distinct=True)).filter(uid__gt=1)
# SELECT u_id, COUNT( DISTINCT ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1 def distinct(self, *field_names)
# 用于distinct去重
models.UserInfo.objects.values('nid').distinct()
# select distinct nid from userinfo 注:只有在PostgreSQL中才能使用distinct进行去重 def order_by(self, *field_names)
# 用于排序
models.UserInfo.objects.all().order_by('-id','age') def extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
# 构造额外的查询条件或者映射,如:子查询 Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid']) def reverse(self):
# 倒序
models.UserInfo.objects.all().order_by('-nid').reverse()
# 注:如果存在order_by,reverse则是倒序,如果多个排序则一一倒序 def defer(self, *fields):
models.UserInfo.objects.defer('username','id')

models.UserInfo.objects.filter(...).defer('username','id')
#映射中排除某列数据 def only(self, *fields):
#仅取某个表中的数据
models.UserInfo.objects.only('username','id')

models.UserInfo.objects.filter(...).only('username','id') def using(self, alias):
指定使用的数据库,参数为别名(setting中的设置) ##################################################
# PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS #
################################################## def raw(self, raw_query, params=None, translations=None, using=None):
# 执行原生SQL
models.UserInfo.objects.raw('select * from userinfo') # 如果SQL是其他表时,必须将名字设置为当前UserInfo对象的主键列名
models.UserInfo.objects.raw('select id as nid from 其他表') # 为原生SQL设置参数
models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12,]) # 将获取的到列名转换为指定列名
name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
Person.objects.raw('SELECT * FROM some_other_table', translations=name_map) # 指定数据库
models.UserInfo.objects.raw('select * from userinfo', using="default") ################### 原生SQL ###################
from django.db import connection, connections
cursor = connection.cursor() # cursor = connections['default'].cursor()
cursor.execute("""SELECT * from auth_user where id = %s""", [1])
row = cursor.fetchone() # fetchall()/fetchmany(..) def values(self, *fields):
# 获取每行数据为字典格式 def values_list(self, *fields, **kwargs):
# 获取每行数据为元祖 def dates(self, field_name, kind, order='ASC'):
# 根据时间进行某一部分进行去重查找并截取指定内容
# kind只能是:"year"(年), "month"(年-月), "day"(年-月-日)
# order只能是:"ASC" "DESC"
# 并获取转换后的时间
- year : 年-01-01
- month: 年-月-01
- day : 年-月-日 models.DatePlus.objects.dates('ctime','day','DESC') def datetimes(self, field_name, kind, order='ASC', tzinfo=None):
# 根据时间进行某一部分进行去重查找并截取指定内容,将时间转换为指定时区时间
# kind只能是 "year", "month", "day", "hour", "minute", "second"
# order只能是:"ASC" "DESC"
# tzinfo时区对象
models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC)
models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai')) """
pip3 install pytz
import pytz
pytz.all_timezones
pytz.timezone(‘Asia/Shanghai’)
""" def none(self):
# 空QuerySet对象 ####################################
# METHODS THAT DO DATABASE QUERIES #
#################################### def aggregate(self, *args, **kwargs):
# 聚合函数,获取字典类型聚合结果
from django.db.models import Count, Avg, Max, Min, Sum
result = models.UserInfo.objects.aggregate(k=Count('u_id', distinct=True), n=Count('nid'))
===> {'k': 3, 'n': 4} def count(self):
# 获取个数 def get(self, *args, **kwargs):
# 获取单个对象 def create(self, **kwargs):
# 创建对象 def bulk_create(self, objs, batch_size=None):
# 批量插入
# batch_size表示一次插入的个数
objs = [
models.DDD(name='r11'),
models.DDD(name='r22')
]
models.DDD.objects.bulk_create(objs, 10) def get_or_create(self, defaults=None, **kwargs):
# 如果存在,则获取,否则,创建
# defaults 指定创建时,其他字段的值
obj, created = models.UserInfo.objects.get_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 2}) def update_or_create(self, defaults=None, **kwargs):
# 如果存在,则更新,否则,创建
# defaults 指定创建时或更新时的其他字段
obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 1}) def first(self):
# 获取第一个 def last(self):
# 获取最后一个 def in_bulk(self, id_list=None):
# 根据主键ID进行查找
id_list = [11,21,31]
models.DDD.objects.in_bulk(id_list) def delete(self):
# 删除 def update(self, **kwargs):
# 更新 def exists(self):
# 是否有结果

最新文章

  1. day9---paramiko ssh ftp
  2. ThreadLocal源码分析
  3. 数据仓库与ODS的区别
  4. tomcat 粗略笔记
  5. as 中的反射 describeType
  6. ARFF文件格式
  7. ural 1572 Yekaterinozavodsk Great Well
  8. mysql导出数据库和恢复数据库代码
  9. C++分布式实时应用框架 (Cpp Distributed Real-time Application Framework)----(一):整体介绍
  10. HTML基础--元素类型及类型转换
  11. iptables配置管理
  12. 随手小代码——Python 从集合中随机抽取元素
  13. SQL Sever 2012版本数据库的完全安装流程
  14. 解码字符串 Decode String
  15. how2j网站前端项目——天猫前端(第一次)学习笔记2
  16. 高通 display 驱动【转】
  17. Logback日志存放路径的问题
  18. Laravel 中的异常处理
  19. 如何将图片嵌入到Html中
  20. 三十二 Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy的暂停与重启

热门文章

  1. WebStorm调节控制台字体
  2. Python起源发展与学(ru)习(keng)的开篇
  3. Shell脚本分析服务器性能
  4. Python学习之旅:使用virtualenv创建Python环境及PyQT5环境配置
  5. super(classname,self).__init__() 作用
  6. JavaScript漫谈之理解类型操作符typeof
  7. SSL证书部署相关知识总结
  8. Spring boot拦截器的实现
  9. Python3-编码问题-解决为何我的python打印总是出现乱码??
  10. J2EE简单的分页器