Django系列之orm查询

表结构概况

现有四张表,表和表之间有一对一、一对多、多对多的关系,具体表结构如下:

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 参数的前提下做的查询。

一对一查询

# 子查询-正查:查询张三的手机号
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,数据库,python)