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()

  

 

posted @ 2020-07-17 19:03  闫世成  阅读(93)  评论(0)    收藏  举报