Django的ORM表查询

目录

  • Django的ORM表查询

    • 单表查询
    • 多表查询
    • 聚合查询
    • 分组查询
    • F与Q查询

Django的ORM表查询

先创建一个数据库,做前期准备

为了方便测试,不再进行urls对应关系和views的书写,直接测试的单个文件

那么如何只单独测试Django中的某个py文件,有以下方法

  • 在任意一个py文件中书写以下代码

    • 可以在应用app的目录下的tests.py中书写
    • 也可以自己建立一个py文件书写
    import os
    
    if __name__ == "__main__":
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test53.settings")
        import django
        django.setup()
    • 到manage.py文件中拷贝即可

单表查询

通过models.py创建一个表

from django.db import models

class Movie(models.Model):
    title = models.CharField(max_length=64)
    price = models.DecimalField(max_digits=8, decimal_places=2)
    publish_time = models.DateField()

导入tests.py文件

from app01 import models
models.Movie.objects.all()
必知必会16条
"""
    必知必会16条
        1.create()
        2.all()
        3.filter()
        4.update()
        5.delete()
        6.first()
        7.last()
        8.get()
        9.values()
        10.values_list()
        11.order_by()
        12.count()
        13.exclude()
        14.exists()
        15.reverse()
        16.distinct()
    """
  1. create()
# creat()   返回值就是当前被创建数据的对象本身
    models.Movie.objects.create(title='三国演义', price=199.99, publish_time='2010-1-1')
    # 直接传日期对象也可以
    from datetime import date
    ctime = date.today()
    models.Movie.objects.create(title='西游记', price=88.88, publish_time=ctime)
  1. all()
# all() 返回queryset对象
    res = models.Movie.objects.all()
    print(res)
  1. filter()
# 3.filter()    返回queryset对象
res = models.Movie.objects.filter(pk=1) # pk就是主键
res = models.Movie.objects.filter(pk=1, title='三国演义')
print(res)
  1. get()---> 不推荐使用,因为当查询条件不存在的时候直接报错
# 4. get()  直接获取对象本身
res = models.Movie.objects.get(pk=2)
print(res.title, res.price, res.publish_time)
  1. values() 获取指定字段对的数据
# 5.values()    返回queryset对象[{},{}]
res = models.Movie.objects.values('title', 'price')
print(res)
  1. values_list() 获取指定字段对的数据
# 6. values_list()  返回queryset对象[(),()]
res = models.Movie.objects.values_list('title', 'price')
print(res)
  1. first() 获取第一个元素对象
# 7.first() 返回数据对象
res = models.Movie.objects.filter().first()
print(res)
  1. last() 获取最后一个元素对象
# 8.last()  返回数据对象
res = models.Movie.objects.filter().last()
print(res)
  1. update() 更新数据
# 9.update()    返回受影响的行数
res = models.Movie.objects.filter(pk=1).update(title='水浒传', price=77.77)
print(res)
  1. delete() 删除数据
# 10.delete()   返回受影响的表及行数
res = models.Movie.objects.filter(pk=1).delete()
print(res)  # (1, {'app01.Movie': 1})
  1. count() 统计数据条数
# 11.count()    返回数据条数
res = models.Movie.objects.count()
print(res)  # 1
  1. order_by() 按照指定字段排序
# 12.order_by() 默认是升序, -号就是降序
# res = models.Movie.objects.order_by('price')
res = models.Movie.objects.order_by('-price')
print(res)
  1. exclude() 排除什么之外
# 13.exclude()
res = models.Movie.objects.exclude(pk=2)
print(res)
  1. exists() 判断是否有数据
# 14.exists()
res = models.Movie.objects.filter(pk=999).exists()
print(res)  # False
  1. reverse() 反转
# 15.reverse()
res = models.Movie.objects.order_by('price').reverse()
print(res)
  1. distinct() 去重:前提是必须是有完全一样的数据才可以
# 16.distinct()
res = models.Movie.objects.values('title', 'price').distinct()
print(res)

双下划线查询

例题

  1. 查询价格大于70的电影
res = models.Movie.objects.filter(price__gt=70)
print(res)
  1. 查询价格小于80的电影
res = models.Movie.objects.filter(price__lt=80)
print(res)
  1. 查询价格大于等于88.88的电影
res = models.Movie.objects.filter(price__gte=88.88)
print(res)
  1. 查询价格小于等于77.77的电影
res = models.Movie.objects.filter(price__lte=77.77)
print(res)
  1. 查询价格是66或77或88
res = models.Movie.objects.filter(price__in=[66, 77, 88])
print(res)
  1. 查询价格在77-99之间的电影
res = models.Movie.objects.filter(price__range=(77,99))
print(res)          # 这里的range顾头也顾尾
  1. 查询电影名字中包含字母DDY的电影
res = models.Movie.objects.filter(title__contains='DDY')
# 默认区分大小写
res = models.Movie.objects.filter(title__icontains='DDY')   # i 忽略大小写
print(res)
  1. 查询2010年出版的电影
res = models.Movie.objects.filter(publish_time__year=2010)
print(res)
  1. 查询是1月份出版的电影
res = models.Movie.objects.filter(publish_time__month=1)
print(res)

多表查询

先在models.py中创建几张表,作为前期准备

外键字段在

  • 1.X版本中默认就是级联更新级联删除的
  • 2.X版本中 则需要你自己手动指定
class Book(models.Model):
    title = models.CharField(max_length=64)
    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')
    # 库存数
    kucun = models.BigIntegerField(default=1000)
    # 售出数
    maichu = models.BigIntegerField(default=500)

class Publish(models.Model):
    name = models.CharField(max_length=64)
    addr = models.CharField(max_length=64)

class Author(models.Model):
    name = models.CharField(max_length=64)
    age = models.IntegerField()

    # 作者详情  一对一,外键字段建在任意一方,推荐查询频率高的一方
    author_detail = models.OneToOneField(to='AuthorDetail')

class AuthorDetail(models.Model):
    phone = models.BigIntegerField()
    addr = models.CharField(max_length=64)
外键字段的增删改查
  • 一对多表关系

# 1.增 直接写实际的表字段,publish_id
models.Book.objects.create(title='三国演义', price=199, publish_id=2)
# 2.增 虚拟字段 直接给对象
publish_obj = models.Publish.objects.get(pk=1)
models.Book.objects.create(title='水浒传', price=188, publish=publish_obj)

# 1.改   同上
models.Book.objects.filter(pk=1).update(publish_id=3)
# 2.改
publish_obj = models.Publish.objects.get(pk=4)
models.Book.objects.filter(pk=1).update(publish=publish_obj)
  • 多对多表关系
  1. 给书籍绑定作者关系(add)
book_obj = models.Book.objects.filter(pk=1).first()
# 书籍和作者的关系是第三张表决定的
# print(book_obj.authors) # 书籍对象.虚拟字段authors就类似于已经跨到书籍和作者的第三张表了
book_obj.authors.add(1) # 给书籍绑定一个主键为1的作者
book_obj.authors.add(2, 3) # 给书籍绑定一个主键为2,3的作者

add是专门给第三张关系表添加数据,括号内即可传入数字,也可传入对象,支持传入多个

  1. 移除书籍与作者的绑定关系(remove)
book_obj = models.Book.objects.filter(pk=1).first()
# book_obj.authors.remove(2)
book_obj.authors.remove(1, 3)
author_obj = models.Author.objects.get(pk=2)
book_obj.authors.remove(author_obj)

remove是专门给第三张关系表移除数据,括号内即可传入数字,也可传入对象,支持传入多个

  1. 修改书籍与作者的关系(set)
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.set((2,))
book_obj.authors.set((2, 3))

set 修改书籍与作者的关系,括号内支持传数字和对象 但是需要是可迭代对象

  1. 清空书籍与作者关系(clear)
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.clear()

clear() 清空关系,不需要任何的参数


跨表查询

跨表查询的方式

  • 子查询:将一张表的查询结果当做另外一张表的查询条件

    • 分步操作
  • 链表查询
    • inner join
    • left join
    • right join
    • union

正反向的概念

  • 正向

    • 跨表查询的时候,外键字段是否在当前数据对象中,如果在,查询另外一张关系表,叫做正向
  • 反向
    • 跨表查询的时候,外键字段是否在当前数据对象中,如果不在,查询另外一张关系表,叫做反向

这里有个口诀

  • 正向查询按外键字段,反向查询按表名小写,__set

基于对象的跨表查询(子查询)

  1. 查询书籍pk为1的出版社的名称
book_obj = models.Book.objects.filter(pk=1).first()
print(book_obj.publish.name)    # 北方出版社
print(book_obj.publish.addr)    # 北京
  1. 查询书籍pk为2的所有作者的姓名
book_obj = models.Book.objects.filter(pk=2).first()
print(book_obj.authors) # app01.Author.None
author_list = book_obj.authors.all()
for author_obj in author_list:
    print(author_obj.name)
  1. 查询作者pk为1的电话号码
author_obj = models.Author.objects.filter(pk=1).first()
print(author_obj.author_detail.phone)

注意:以上为正向查询,当外键字段对应的数据可以有多个的时候,需要加.all(),否则点外键字典即可获取到对应的数据对象

  1. 查询出版社名称为东方出版社出版过的书籍
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
print(publish_obj.book_set) # app01.Book.None
book_list = publish_obj.book_set.all()
for book_obj in book_list:
    print(book_obj.title)
  1. 查询作者为jason写过的书
author_obj = models.Author.objects.filter(name='jason').first()
book_list = author_obj.book_set.all()
for book_obj in book_list:
    print(book_obj.title)
  1. 查询手机号为120的作者姓名
author_detail_obj = models.AuthorDetail.objects.filter(phone=120).first()
print(author_detail_obj.author.name)

注意:基于对象的反向查询,表名小写是否需要加_set.all()
一对多和多对多的时候需要添加,一对一不需要添加



基于双下划线跨表查询(链表查询)

  1. 查询书籍pk为1的出版社名称
# 正向:
    res = models.Book.objects.filter(pk=1).values('publish__name')
    print(res)
# 反向:
    res = models.Publish.objects.filter(book__pk=1).values('name')
    print(res)
  1. 查询书籍pk为1的作者姓名和年龄
# 正向
    res = models.Book.objects.filter(pk=1).values('authors__name', 'authors__age', 'title')
    print(res)
# 反向
    res = models.Author.objects.filter(book__pk=1).values('name', 'age', 'book__title')
    print(res)
  1. 查询作者是jason的年龄和手机号
# 正向
    res = models.Author.objects.filter(name='jason').values('age', 'author_detail__phone')
    print(res)
# 反向
    res = models.AuthorDetail.objects.filter(author__name='jason').values('author__age', 'phone')
    print(res)
  1. 查询书籍pk为1的作者的手机号
# 正向
    res = models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
    print(res)
# 反向
    res = models.AuthorDetail.objects.filter(author__book__pk=1).values('phone')
    print(res)

注意:只要表与表之间有关系,就可以通过正向的外键字段或者反向的表名小写连续跨表操作


聚合查询

关键字是 aggregate

聚合查询需要导入几个功能

from django.db.models import Max, Min, Avg, Sum, Count
  1. 查询所有书的平均价格
res = models.Book.objects.aggregate(avg_price=Avg('price'))
    print(res)
  1. 查询价格最贵的书
res = models.Book.objects.aggregate(max_price=Max('price'))
    print(res)
  1. 全部使用
res = models.Book.objects.aggregate(Avg('price'), Max('price'), Min('price'), Sum('price'), Count('price'))
print(res)

分组查询

关键字是 annotate

  1. 统计每一本书的作者个数
res = models.Book.objects.annotate(author_num=Count('authors')).values('title', 'author_num')
    print(res)
  1. 统计出每个出版社卖的最便宜的书
res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name', 'min_price')
    print(res)
  1. 统计不止一个作者的图书
res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('title')
    print(res)
  1. 查询各个作者出的书的总价格
res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name', 'sum_price')
    print(res)

如何按照表中的某一个指定字段分组

model.Book.objects.values('price').annotate()
# 这样就是以书表中价格分组

F与Q查询

需要导入

from django.db.models import F, Q

F:

  1. 查询库存数大于卖出数的书籍
book_list = models.Book.objects.filter(kucun__gt=F('maichu'))
    for book_obj in book_list:
        print(book_obj.title)
  1. 将所有书的价格提高100
res = models.Book.objects.update(price=F('price')+100)
    print(res)  # 5 返回影响的数据条数

F可以帮我们获取表中某个字段对应的值

Q:

Q可以改变查询的条件关系 与或非 (and、or、not)

  1. 查询书的名字是三国演义或者价格是400的书籍
res = models.Book.objects.filter(Q(title='三国演义'), Q(price=400)) # 逗号,是and关系
res1 = models.Book.objects.filter(Q(title='三国演义')|Q(price=400)) # | 管道符是 or关系
res2 = models.Book.objects.filter(~Q(title='三国演义')|Q(price=400))    # ~是not关系

Q的用法:想要

res = models.Book.objects.filter(‘title‘=‘三国演义‘)

title和三国演义都可以成为字符串,这样可以让用户自己选择想要的条件

q = Q()默
    q.connector = 'or'  # q对象认也是and关系,可以通过connector改变or
    q.children.append(('title', '三国演义'))
    q.children.append(('price', 1000))
    res = models.Book.objects.filter(q)
    print(res)

原文地址:https://www.cnblogs.com/YGZICO/p/12198736.html

时间: 2024-08-29 02:28:52

Django的ORM表查询的相关文章

Django开发之路 二(django的models表查询)

django的models表查询 一.单表查询 (1) all(): 查询所有结果 # 返回的QuerySet类型 (2) filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 #返回的QuerySet类型 (3) get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个, #返回的models对象 如果符合筛选条件的对象超过一个或者没有都会抛出错误. (4) exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象 #返回的Query

Django 之多表查询 与多表的使用

1.django的多表查询 主要区分为: 正向查询    逆向查询 1. 多表查询: 是一个复杂的查询,他分为对象查询和__模糊查询两种方式 2. 多表查询: 又分为 一对一查询, 一对多查询, 多对多查询 三种方式 3. 多表查询: 分为正向查询 与 逆向查询, 正向查询 是根据 这个表中的外键属性名开始出发查询的跨表查询 逆向查询 是根据 根据关联表的 类名 小写 开始 进行跨表查询 4. 多表查询: 外键的存放位置如下: # 一对多:出版社(一) 书籍(多,外键在多的一方,依赖于出版社)

django之多表查询操作

基于双下划线的跨表查询(连表查询 join) select emp.name from emp inner join dep on emp.dep_id = dep.id where dep.name='技术'; select emp.name from dep inner join emp on emp.dep_id = dep.id where dep.name='技术'; 示例: # 一对一 # 查询一下王洋的电话号码 # ret = models.Author.objects.filte

Django之跨表查询及添加记录

一:创建表 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);     一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many). 创建一对一的关系:OneToOne("要绑定关系的表名") 创建一对多的关系:ForeignKey("要绑定关系的表名") 创建多对多的关系:ManyToMany("要绑定关系的表名"

django之多表查询与创建

https://www.cnblogs.com/liuqingzheng/articles/9499252.html # 一对多新增数据 添加一本北京出版社出版的书 第一种方式 ret=Book.objects.create(name='红楼梦',price=34.5,publish_id=1) print(ret.name) 第二种方式,存对象publish=出版社的对象,存到数据库,是一个id publish=Publish.objects.get(id=1) pk是主键,通过主键查找 pu

Django之跨表查询——正反向查询(ForeignKey)

1.正向查询和反向查询: 外键的查询操作: 正向查询: # 正向查询 # 基于对象,跨表查询 book_obj = models.Book.objects.all().first() ret = book_obj.publisher # 和我这本书关联的出版社对象 print(ret,type(ret)) ret = book_obj.publisher.name # 和我这本书关联的出版社对象的name属性 print(ret,type(ret)) # 查询id=1的书出版社名称 # 涉及到跨

Django中多表查询思路

需求: 1.有一张文章表和一张评论表 2.两张表的关系是一对多 3.规则:若是有新评论,则将对应的文章置顶,若是有新文章则将新文章置顶. 思路: 在文章表中增加一个最后评论时间的字段.然后采用分组排序,即可解决 预留: Django中除了有外键对应关系表外,如何将多张表联合查询?

Django【orm】查询

本文主要列举一下django orm中的常用查询的筛选方法: 大于.大于等于 小于.小于等于 in like is null / is not null 不等于/不包含于 其他模糊查询 model: class User(AbstractBaseUser, PermissionsMixin): uuid = ShortUUIDField(unique=True) username = models.CharField(max_length=100, db_index=True, unique=T

Django models 单表查询

从数据库中查询出来的结果一般是一个集合,这个集合叫做 QuerySet 1. 查看Django QuerySet执行的SQL .query.__str__()或 .query属性打印执行的sql语句 from quicktool.models import User from django.http import HttpResponse Creat = User.objects.all().filter(created=1557222940).query.__str__() return Ht