Django ORM 进阶操作
快速入门
常用操作
1) all(); 查询所有结果 2) filter(**kwargs) 查询筛选条件的对象 3) get(**kwargs) 查询筛选条件的对象,且只能返回一个不能返回或者返回多个都报错. 4) exclude(**kwargs) 查询与筛选对象不匹配的对象. 5) values(*field) 返回 valueQuerySet 一个特殊的 QuerySet,得到并不是model 的实例对象而是可迭代的字典序列. 6) values_list(*field) 返回一个元祖序列. 7) order_by(*field) 对查询结果排序. 8) reverse() 对查询结果反向排序,通常只能在具有以定义顺序的QuerSet上调用,(在model类的Meta中指定ordering或调用order_by()方法)。 9) distinct() 从返回结果中剔除重复记录,(如果你查询跨越多个表,可能在计算QuerySet时得到重复的结果。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重。) 10) count(); 返回数据库中匹配查询(QuerSer的对象数量) 11) first() 返回第一条记录 12) last() 返回最后一条记录 13) exists() 如果 QuerySet 包含数据则返回True,否则则返回False.
返回方法类型
返回QuerySet对象的方法
- all()
- fiter()
- exclude()
- order_by()
- reverse()
- distinct()
特殊QuerySet
- values() 返回一个可迭代字典
- values_list() 返回一个可迭代的元祖列表
返回具体对象
- get()
- first()
- last()
返回布尔值
- exists()
返回数字的方法
- count()
单表查询之双下划线
1) __in # 在 .. 内 2) __range # 在 .. 范围内 3) __cotains # 模糊查询 4) __icontains # 模糊查询不区分大小写 5) __exact # 等价于 = 绝对 6) __exclude # 取反 7) __lt # 小于 8) __lte # 小于等于 9) __gt # 大于 10) __gte # 大于等于 11) __iregex # 正则匹配 12) __isnull # 判断是否为空 返回 True/False 13) __endswith # 以...结尾 14) __iendswith # 不区分大小写 以...结尾 15) __startswith # 以... 开头 16 __istartswith # 以...开头 不区分大小写
示例:
1 # 1) 找出bookid 大于2 小于六的书籍 2 books = models.Books.objects.filter(id__lt=6,id__gt=2) 3 print(books) 4 # 2) 找出 id 是 [1,5,9,10] 的出版社 5 publisher = models.Publisher.objects.filter(id__in=[1,5,9,10]) 6 print(publisher) 7 8 # 3) 找出 书籍名称包含 python 的书籍,两种方式 9 book1 = models.Books.objects.filter(title__contains='python') 10 print(book1) 11 book2 = models.Books.objects.filter(title__icontains='PYTHON') 12 print(book2) 13 14 # 4) 找出 id 范围在 1-5 的作者. 15 authors = models.Authors.objects.filter(id__range=[1,5]) 16 print(authors) 17 18 # 5) 找出 1998 年出生的作者 19 # AuthorDetail = models.AuthorDetail.objects.filter(birthday__year=1998).values('authors__name') 20 # print(AuthorDetail) 21 # pub_obj = models.Publish.objects.filter(name='北大出版社').first() 22 # print(pub_obj.book_set.all()) 23 AuthorDetail = models.AuthorDetail.objects.filter(birthday__year=1998).first() 24 print(AuthorDetail.authors.name)
ORM基本操作
查
一对一
正向查询: 对象.关联字段.字段
反向查询: 对象.表名小写.字段
1) 查询 年龄大于 23 小于 29 的作者姓名和手机号
obj = models.Authors.objects.filter(age__gt=23,age__lt=29).first()
print(obj.name)
print(obj.autordeail.telephone)
obj = models.Authors.objects.filter(age__gt=23, age__lt=29)
for field in obj:
print(field,field.autordeail.telephone)
2) 查询 刘备的手机号是多少
obj = models.Authors.objects.filter(name='刘备').first()
print(obj.autordeail.telephone)
一对多
正向查找: 对象.关联字段.字段
反向查找: 对象.表名小写_set.all()
#1) 查询 西游记是哪个出版社出版 obj = models.Books.objects.filter(title='西游记').first() print(obj.publisher.name) #2) 查询 凤凰出版传媒股份有限公司 出版了那些书 作者分别都是谁 obj = models.Publisher.objects.filter(name='凤凰出版传媒股份有限公司').first() print(obj.books_set.all())
多对多
正向查找: 对象.关联属性.all()
反向查找: 对象.表名小写._set.all()
1) 查询 西游记是哪个出版社出版 和 作者
obj = models.Books.objects.filter(title='西游记').first()
print(obj.publisher.name,obj.authors.all())
2) 查询 凤凰出版传媒股份有限公司 出版了那些书 作者分别都是谁
obj = models.Publisher.objects.filter(name='凤凰出版传媒股份有限公司').first()
books_obj = obj.books_set.all()
for book in books_obj:
print(book,book.authors.all())
基于对象的跨表查询
# 一对一 # 正向查询: 对象.values('关联字段__字段') # 反向查询: filter(关联字段__字段=值) 1) 查询 孙权的电话号码 obj = models.Authors.objects.filter(name='孙权').values('autordeai__telephone') print(obj[0]) 2) 查询 18976788899 电话号码是谁的 obj = models.AuthorDetail.objects.filter(telephone='18976788899').values('telephone','authors__name') print(obj) obj = models.Authors.objects.filter(autordeai__telephone='18976788899').values('name') print(obj) # 一对多 # 正向: 对象.values('关联字段__字段') # 反向: filter(小写表名__字段=值) 1) 查询 水浒传是哪个出版社出版的. obj = models.Books.objects.filter(title='水浒传').values('publisher__name') print(obj) obj = models.Publisher.objects.filter(books__title='水浒传').values('name') print(obj) # 多对多 # 正向 对象.values('关联字段__字段') # 反向 filter(小写类名__字段=值) 1) 查询 红楼梦 的作者 obj = models.Books.objects.filter(title='红楼梦').values('authors__name') print(obj) obj = models.Authors.objects.filter(books__title='红楼梦').values('name') print(obj) 2) 查询 曹操谢了那些书 obj = models.Books.objects.filter(authors__name='曹操').values('title') print(obj) obj = models.Authors.objects.filter(name='曹操').values('books__title') print(obj)
增
一对一
1) 增加 作者: 姓名 杨玉环 性别 女 年龄 27 住址 北京市延庆县 生日 19940522 手机号 18976788899
new_detail = models.AuthorDetail.objects.create(
birthday='1994-05-22',
telephone='18976788899',
addr="北京市延庆县",
)
new_author = models.Authors.objects.create(
name='杨玉环',
age=27,
sex=1,
autordeail=new_detail,
)
new_detail1 = models.AuthorDetail.objects.create(
birthday='1992-05-22',
telephone='17778786767',
addr="北京市怀柔区",
)
new_detail2 = models.AuthorDetail.objects.create(
birthday='1993-05-22',
telephone='19990908989',
addr="北京市密云区",
)
2) 指定单表 id 增加作者
obj = models.AuthorDetail.objects.filter(pk=11).first()
new_author = models.Authors.objects.create(
name='王子林',
age=28,
sex=0,
autordeail=obj,
)
一对多
# 增加一本书 ((书名,武松打虎),(作者,刘备,曹操),(售价,100),(简介,一本好书),(出版社状态,已出版),(出版社,山东出版集团有限公司),)
publisher_obj = models.Publisher.objects.filter(name='山东出版集团有限公司').first()
new_book = models.Books.objects.create(
title='武松打虎',
price=100,
good=1000,
abstract='一本好书!',
publisher_state=2,
publisher=publisher_obj
)
多对多
1) 增加 武松上山打老虎 的作者为刘备,曹操 author_obj = models.Authors.objects.filter(name__in=['刘备','曹操']) book_obj = models.Books.objects.filter(title='武松上山打老虎').first() print(author_obj,book_obj) book_obj.authors.add(*author_obj)
改
改都一样
1) 修改作者王子林住址为北京市怀柔区 年龄 29
obj = models.AuthorDetail.objects.filter(addr='北京市怀柔区').first()
check_author = models.Authors.objects.filter(name='王子林').update(
age=29,
autordeail=obj,
)
2) 修改名称为: 武松打虎的书名为 武松上山打老虎
obj = models.Books.objects.filter(title='武松打虎').update(
title='武松上山打老虎'
)
删
- on_delete=models.SET_NULL, 关联字段被删除本字段会置为空, 删除本字段被关联字段会被保留.
- on_delete=models.CASCADE, 关联字段被关联自身也会被删除,删除本字段被关联字段保留.(级联删除)
obj = models.Authors.objects.filter(name='王子林').first().delete() obj = models.AuthorDetail.objects.filter(pk=9).first().delete() 特殊方法 对于ForeignKey对象,clear()和remove()方法仅在null=True时存在。 obj = models.Book.objects.filter(id=5).first() # 根据id 删除作者 obj.authors.remove(3) obj.authors.remove(*[3,4]) obj.authors.clear() # 清空 obj.authors.set(*['1','4']) # 先清空在设置
其他方法
聚合
from django.db.models import Avg, Max, Min, Sum, Count
# 1) Count 统计有几本书
obj = models.Books.objects.all().aggregate(a=Count('title'))
print(obj)
#2) Sum 计算所有书籍的价钱.
obj = models.Books.objects.all().aggregate(Sum('price'))
print(obj)
#3) 最便宜和最贵的书分别是多少钱
obj = models.Books.objects.all().aggregate(Max('price'),Min('price'))
print(obj)
#4) 求所有书价格的平均值
obj = models.Books.objects.all().aggregate(Avg('price'))
print(obj)
F查询
F查询主要提供的是针对两个字段的值做比较.
Django 提供 F()来做这样的比较, F()的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值.
F支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。
from django.db.models import F
from django.db.models import Count
#1) 找到点赞数大于价格加12000的书籍的总数
obj = models.Books.objects.filter(good__gt=F('price')+12000).aggregate(Count('title'))
print(obj)
# 2) 所有的书籍价格增加 10 块
obj = models.Books.objects.all().update(price=F('price')+10)
Q查询
from django.db.models import Count, Q
# 查询作者是 刘备 关于 曹操的书籍
obj = models.Books.objects.filter(Q(authors__name='刘备')|
Q(authors__name='关羽')|
Q(authors__name='曹操')).aggregate(Count('title'))
print(obj)
#2) 查询价格 大于 150 小于300的书籍
ob = models.Books.objects.filter(
Q(price__gt=150)&
~Q(price__gt=300)
)
print(ob)
# 3) Q 对象的另一种使用方式
q = Q()
q.connector = 'OR'
q.children.append(Q(('name__icontains','刘备')))
q.children.append(Q(('name__icontains','曹操')))
q.children.append(Q(('name__icontains','张')))
q.children.append(Q(('name__icontains','王')))
obj = models.Authors.objects.filter(q)
print(obj)
题外操作
终端打印执行SQL
在Django项目的settings.py文件中,在最后复制粘贴如下代码:
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", "book_project.settings")
import django
django.setup()
from app01 import models
books = models.Books.objects.all()
print(books)
方式二:
import os
import sys
# 初始化
def setup():
BASEDIR = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, BASEDIR)
sys.path.insert(0, os.path.abspath(os.path.join(BASEDIR, '..')))
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "book_project.settings")
import django
django.setup()
# 业务逻辑
def test():
from app01 import models
pass
# 入口函数#
def main():
setup()
test()
if __name__ == '__main__':
main()
作者:闫世成
出处:http://cnblogs.com/yanshicheng
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。如有问题或建议,请联系上述邮箱,非常感谢。

浙公网安备 33010602011771号