表结构概况
现有四张表,表和表之间有一对一、一对多、多对多的关系,具体表结构如下:文章来源:https://www.toymoban.com/news/detail-605429.html
class Publish(models.Model):
name = models.CharField(max_length=32)
city = models.CharField(max_length=8)
email = models.CharField(max_length=16)
def __str__(self):
return self.name
class AuthorDetail(models.Model):
gender = models.CharField(max_length=8)
birthday = models.DateField()
telephone = models.BigIntegerField()
addr = models.CharField(max_length=64)
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
ad = models.OneToOneField(AuthorDetail, on_delete=models.CASCADE, null=True)
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
pub_date = models.DateField()
publish = models.ForeignKey(Publish, on_delete=models.CASCADE, null=True)
authors = models.ManyToManyField(Author, db_table="book2author")
def __str__(self):
return self.title
以下的这些查询,都是没有设置 related_name
参数的前提下做的查询,如果要在有 related_name
参数下查询,可以参考文章 related_name的反向查询文章来源地址https://www.toymoban.com/news/detail-605429.html
一对一查询
# 子查询-正查:查询张三的手机号
queryset = Author.objects.get(name="张三").ad.telephone
# 子查询-反查:查询作者详情id为1的作者名(表名小写)
queryset = AuthorDetail.objects.get(id="1").author.name
# 连表查询-正查:查询张三的手机号
queryset = Author.objects.filter(name='张三').values("ad__telephone")
# 连表查询-反查
queryset = AuthorDetail.objects.filter(author__name="张三").values("telephone")
一对多查询
# 子查询-正查: 查询《大圣归来》这本书的出版社地址
queryset = Book.objects.get(title="大圣归来").publish.name
# 子查询-反查: 查询 人民教育出版社 出版的所有书籍
queryset = Publish.objects.get(name="人民教育").book_set.all()
# 连表查询-正查: 查询《大圣归来》这本书的出版社地址
queryset = Book.objects.filter(title="大圣归来").values("publish__name")
# 连表查询-反查
queryset = Publish.objects.filter(book__title="大圣归来").values("name") # values和value_list是QuerySet的方法,而不是Object的方法
queryset = Publish.objects.get(book__title="大圣归来").name # 只有Object才能 .属性
多对多查询
# 子查询-正查:查询《大圣归来了》的所有作者
queryset = Book.objects.get(title="大圣归来了").authors.all().values("name")
# 子查询-反查:查询张三写的所有书籍
queryset = Author.objects.get(name="张三").book_set.all().values("title")
# 连表查询-正查:查询《大圣归来了》的所有作者
queryset = Book.objects.filter(title="大圣归来了").values("authors__name")
# 连表查询-反查
queryset = Author.objects.filter(book__title="大圣归来了").values("name")
跨多张表联合查询
# 查询:南方教育出版社 出版过的所有书籍的名字以及作者的姓名
queryset = Publish.objects.filter(name="南方教育").values("book__title", "book__authors__name")
queryset = Book.objects.filter(publish__name="南方教育").values("title", "authors__name")
queryset = Author.objects.filter(book__publish__name="南方教育").values("name", "book__title")
# 查询:手机号包含8的作者出版过的所有书籍名称以及出版社名称
queryset = Publish.objects.filter(book__authors__ad__telephone__contains='8').values("name", "book__title")
queryset = AuthorDetail.objects.filter(telephone__contains="8").values("author__book__title", "author__book__publish__name")
queryset = Book.objects.filter(authors__ad__telephone__contains="8").values("title", "publish__name")
聚合分组查询
""" 聚合查询 """
# 计算所有图书的平均价格
queryset = Book.objects.all().aggregate(avg_price=Avg("price"))
# 计算所有图书的作者的平均年龄
queryset = Book.objects.all().aggregate(avg_age=Avg("authors__age"))
""" 分组查询: 按哪个字段分组,values就是那个值 """
# 查询每一个作者出版的书的数量
queryset = Book.objects.values("authors").annotate(cnt=Count("*"))
# 查询每一个作者的名字以及出版书籍的个数
queryset = Author.objects.values("name").annotate(pub_count=Count("book"))
# 查询每一个出版社的名字和出版过的书籍的平均价格
queryset = Publish.objects.values("name").annotate(avg_price=Avg("book__price"))
# 查询每一个书籍的名称以及作者的个数
queryset = Book.objects.values("title").annotate(author_count=Count("authors")).values("title", "author_count")
# 查询作者个数大于1的每一本书籍的名称和作者个数
# 如果不写values的话,就默认按照id分组
queryset = Book.objects.annotate(author_cnt=Count("authors")).filter(author_cnt__gt=1).values("title", "author_cnt")
# 查询书籍名称包含 "h" 的书籍名称和作者个数(先筛选再连表查)
queryset = Book.objects.filter(title__contains="h").annotate(book_cnt=Count("authors")).values("title", "book_cnt")
F查询和Q查询
""" F 查询: 针对某一列进行运算或其他操作 """
# 查询评论数大于2倍点赞数的文章
queryset = Article.objects.filter(comment_num__gt=F("poll_num")*2)
# 对数据库做修改操作:将所有的书籍的价格提高100元
queryset = Book.objects.update(price=F("price")+100)
""" Q查询:多个条件的and、or、not操作 """
# or:查询价格大于300或者名称以p开头的书籍
queryset = Book.objects.filter(Q(price__gt=300) | Q(title__startswith="p"))
# and: 查询价格大于300并且名称以p开头的书籍
queryset = Book.objects.filter(Q(price__gt=300) & Q(title__startswith="大圣")) # 下面两者是等价的
queryset = Book.objects.filter(price__gt=300, title__startswith="大圣")
到了这里,关于Django系列之orm查询的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!