Django-ORM查询

1.单表查询--必知必会的13条

函数名 说明 用法 返回值 注意事项
all() 查询所有 Book.object.all() queryset -
filter(*fields) 条件查询 Book.object.filter(title="三国演义") queryset -
get(*fields) 条件查询 Book.object.get(title="三国演义") model_obj 查询结果没有或者多个会报错
first() 第一条 Book.object.filter(title="三国演义").first() model_obj -
last() 最后一条 Book.object.filter(title="三国演义").last() model_obj -
order_by(*fields) 排序 Book.objects.all().order_by("price") queryset .order_by("-price")倒叙order_by("-price","pub_date")多条件排序
exclude(*fields) 排除 Book.objects.exclude(price=123) queryset -
count() 计数/查询条数 Book.objects.all().count() int -
reverse() 反向排序 Book.objects.all().order_by("title").reverse() queryset -
exists() 查询条件时候存在数据 Book.objects.all().exists() bool -
values(*fields) 返回需要的的字段 Book.objects.all().values("title","price") dict -
values_list(*fields) 返回需要的的字段的数据 Book.objects.all().values_list("title", "price") tuple -
distinc() 去重 Book.objects.all().values("title").distinc() dict / tuple 一般会与values、values_list组合使用

2.单表查询--模糊查询

  • 使用双下划线 '__'
字段名 说明 用法 注意事项
__gt 大于
__gte 大于等于
__lt 小于
__lte 小于等于
__startwith 以什么开始
__istartwith 以什么开始不区分大小写
__endwith 以什么结束
__iendwith 以什么结束 不区分大小写
__contains 包含
__icontains 包含什么 不区分大小写
__in 在什么里面的
__range 在什么范围之间的
__year 年份等与多少的
__month 月份等于多少的

下面查询用到的表关系

class Book(models.Model):

    nid = models.AutoField(primary_key=True)  # 主键 自增
    title = models.CharField(max_length=64,verbose_name="书籍名称")  # 字符形式 最大长度32
    price = models.DecimalField(max_digits=8,decimal_places=2,verbose_name="书籍价格")  # 浮点型999999.99  最大长度 8位  小数点后2位
    comment_count = models.CharField(max_length=32, verbose_name="评论数量")
    poll_count = models.CharField(max_length=32, verbose_name="点赞数量")
    pub_date = models.DateTimeField(verbose_name="出版日期")  # "2012-12-12"
    publish = models.ForeignKey(to="Publish",on_delete=models.CASCADE, verbose_name="正向关联出版社字段")  # 级联删除
    authors = models.ManyToManyField(to="Author", verbose_name="正向关联作者字段")

    def __str__(self):
        return self.title  # queryset  显示的名称

    class Meta:
        verbose_name="书籍表"


class Publish(models.Model):

    nid = models.AutoField(primary_key=True, verbose_name="主键")
    name = models.CharField(max_length=32, verbose_name="出版社名称")
    email = models.CharField(max_length=32, verbose_name="出版社邮箱")

    def __str__(self):
        return self.name  # queryset  显示的名称

    class Meta:
        verbose_name = "出版社表"


class Author(models.Model):

    name = models.CharField(max_length=32, verbose_name="作者名字")
    age = models.IntegerField(verbose_name="年龄")
    email = models.CharField(max_length=32, verbose_name="邮箱")
    ad = models.OneToOneField(to="AuthorDrtail",on_delete=models.CASCADE,verbose_name="正向关联的作者详情字段")

    def __str__(self):
        return self.name  # queryset  显示的名称

    class Meta:
        verbose_name = "作者表"

class AuthorDrtail(models.Model):

    addr = models.CharField(max_length=32, verbose_name="作者住址")
    tel = models.IntegerField(verbose_name="作者手机号")

    def __str__(self):
        return self.tel  # queryset  显示的名称

    class Meta:
        verbose_name = "作者详情表"

3.表关联查询 基于对象的跨表查询(子查询)

  • 一对多
            正向查询: 按字段 book.publish
    Book    -----------------------------  Publish
            反向查询: 表名的小写_set.all()
# 查询python出版社的名字 和邮箱   书查出版社   -对多查询
    book_obj = Book.objects.filter(title="python").first()
    publish_obj = book_obj.publish
    publish_obj.name
    publish_obj.email

    # 查询苹果出版社 出版的所有书籍名称
    pub_obj = Publish.objects.get(name="苹果出版社")
    publish_obj.book_set.all().values("title")  # queryset

    # 查询 jack 出版的所有书籍名称
    author = Author.objects.filter(name="Jack").first()
    author.book_set.all()
  • 多对多
            正向查询  book.author.all()
    Book -----------------------------------Author
            反向查询  表名小写_set.all()  jack.book_set.all().values("age")

  • 一对一
            正向查询 author.ad
    Author ----------------------- AuthorDetail
            反向查询 ad.author    : ad.表名小写

4.表关联查询 基于双下划线 __ 的跨表查询(join 即 一次查询)


"""
    一对多
            正向查询 按字段
    Book    ---------------------   Publish
            反向查询 按表名小写
"""
    # 查询书籍名为 python 的出版社的 名字  一对多
    Book.objects.filter(title="python").values("publish__name")  # 正向查询
    Publish.objects.first(book__title="python").values('name')  # 反向查询

    # 查询 北京出版社 出版社的书籍 名称 一对多
    Publish.objects.filter(name="北京出版社").values('book__title')
    Book.objects.filter(pulish__name='北京出版社').values('title')



    # 查询 python 这本书的作者的年龄  多对多
    Book.objects.filter(title='python').values("authors__age")
    Author.objects.filter(book__title='python').values('age')
    return HttpResponse("查询成功")

    # 查询 Jack 出版的书籍的 名称  多对多
    Author.objects.filter(name='Jack').values("book__title")
    Book.objects.filter(authors__name='Jack').values('title')

    # 查询 Jack的手机号  一对一
    Author.objects.filter(name='Jack').values("ad__tel")
    AuthorDrtail.objects.filter(author__name="Jack").values("tel")
    
    # 查询手机号为131 的作者的名字  一对一
    AuthorDrtail.objects.filter(tel=131).values('author__name')
    Author.objects.filter(ad__tel=131).values('name')

5. 连续跨表查询

# 查询 人民出版社 出版过的多有书籍的名字以及作者的名字
Publish.objects.filter(name="人民出版社").values("book__title","book__authors__name")
Book.objects.filter(publish__name="人民出版社").values("title","authors__name") Author.objects.filter(book__publish__name="人民出版社").values('book__title','name')
 # 手机号以 151 开头的作者出版过的所有书籍名称以及出版社的名称
AuthorDrtail.objects.filter(tel__startwith=151).values('author__book__title',"author__book__publish__name")
Author.objects.filter(ad__tel__startwith=151).values("book__title",'book__publish__name')

6. 聚合 分组查询

  • 导入集合函数from django.db.models import Avg,Max,Sum, Min, Count
##############    聚合max min count min avg   #########

    from django.db.models import Avg,Max,Sum, Min, Count
    # 查询多有书籍的平均价
    Book.objects.all().aggregate(priceAvg=Avg("price"))  # {"avg_price":123.00}  可以重命名
    # 查询是多有书籍的个数
    Book.objects.all().aggregate(c=Count("nid"))  # {"c":4}

    ##############    分组(group by)查询    #########

    # 查询书籍表每个出版社id以及对应的个数
    # key : annotate  前 select 那个字段就按照 那个字段group by
    Book.objects.values('publish_id').annotate(c=Count(1))  # 返回值
    '''
    select Count(1)m from book GROUP BY publish_id
    '''

    # 跨表查询
    #查询出版社出版的名称以及对应的书籍平均价格
    Publish.objects.values('name').annotate(avg_price=Avg("book__price"))  # book__price Book表中的price
# 简单的写法 现联表查询出所有  再选择要筛选的字段
    Publish.objects.annotate(avg_price='book_price').values('name',"avg_peice")

6. F(获取字段值) 与 Q (关系) 查询

    ##################  F     #################
    from django.db.models import F, Q

    # 查询 评论数 大于 点赞数的 书籍名称
    Book.objects.filter(comment_count__gt=F(poll_count)).values("title")

    # 查询评论数 大于 2倍点赞数的书籍名称
    Book.objects.filter(commnet_count__gt=F(poll_count)*2).values("title")

    # 批量有规律的更新  所有的书籍几个提升100 或者 提升1倍
    Book.objects.all().update(price=100+F("price"))
    Book.objects.all().update(price=F("price")*2)


##################  Q  查询   #################
# 查询价格大于 300 或者 评论数大于3000的书籍

    """
    运算符号   &与   |或   ~非
    """

    Book.objects.filter(Q(price__gt=300)|Q(comment_count__gt=3000))
    Book.objects.filter(~Q(Q(price__gt=300)|Q(comment_count__gt=3000)&Q(poll_count__lt=2000)))

你可能感兴趣的:(Django-ORM查询)