1. 程式人生 > >Django之ORM跨表操作

Django之ORM跨表操作

Django 跨表查詢 F Q

一、準備數據庫

models.py文件內容:

from django.db import models
# Create your models here.
class Book(models.Model):
    title=models.CharField(max_length=32)
    price=models.DecimalField(max_digits=6,decimal_places=2)
    create_time=models.DateField()
    memo=models.CharField(max_length=32,default="")
    publish=models.ForeignKey(to="Publish",default=1)       #定義一對多關系,會在book表添加publish_id字段
    author=models.ManyToManyField("Author")                 #定義多對多關系,會專門生成一張book和author的關系表
    def __str__(self):
        return self.title
class Publish(models.Model):
    name=models.CharField(max_length=32)
    email=models.CharField(max_length=32)
class Author(models.Model):
    name=models.CharField(max_length=32)
    def __str__(self):return self.name


#執行下面python語句生成相關表

python3 manage.py makemigrations
python3 manage.py migrate


添加數據後各個表數據如下:

技術分享圖片 技術分享圖片


技術分享圖片 技術分享圖片


技術分享圖片

二、基於對象的跨表查詢

1、一對一關系

(1)查詢wang的手機號(反向查詢,按表名小寫)

obj = Author.objects.filter(name="wang").first()                           # 得到name="wang"的作者的對象
print(obj.authordetail.tel)                    # obj.authordetail表名得到作者對應的詳細信息對象,再 .tel得到結果 18971232312

(2)查詢手機號為13451222125的作者的名字 (正向查詢,按字段)

obj = AuthorDetail.objects.filter(tel="13451222125").first()           # 得到tel="13451222125"的作者詳細信息的對象
print(obj.author.name)                      # obj.author字段得到作者對象,再 .name得到結果 li


2、一對多關系

(1)查詢id=15的書籍的出版社的名稱(正向查詢,按字段)

book_obj = Book.objects.filter(id=15).first()                  #得到id=15的數的對象
print(book_obj.publish.name)              # book_obj.publish得到書對應的出版社對象,再.name得到出版社的名字 上海出版社


(2)查詢天津出版社出版過的書籍名稱(反向查詢,按表名小寫_set)

publish_obj = Publish.objects.filter(name="天津出版社").first()  #得到name="天津出版社"的出版社對象
print(publish_obj.book_set.all())           # 得到出版社出版的書籍的對象集合:<QuerySet [<Book: go>, <Book: 操作系統原理>]>
for book in publish_obj.book_set.all():
    print(book.title)                                #遍歷得到結果:go和操作系統原理

3、多對多關系

(1)查詢(1)查詢書名為go的所有作者的名字(正向查詢,按字段)

obj = Book.objects.filter(title="go").first()                    #得到書名為go的對象
for i in obj.author.all():                                                   # obj.author.all()得到對應作者的集合
    print(i.name)                                                              # 遍歷得到結果:wang和zhang


(2)查詢zhang出版過的所有書籍名稱(反向查詢,按表名小寫_set)

obj = Author.objects.filter(name="zhang").first()               #得到名字為"zhang"的作者的對象
for i in obj.book_set.all():                                 # obj.book_set.all()得到對應書籍的集合
    print(i.title)                                    # 遍歷得到結果:go,操作系統原理,Linux,python
    
print(obj.book_set.all().values("title"))             # 結果:<QuerySet [{'title': 'go'}, {'title': '操作系統原理'}, {'title': 'Linux'}, {'title': 'python'}]>

三、基於queryset查詢

1、一對一關系

(1)查詢wang的手機號(反向查詢,按表名小寫)

ret = Author.objects.filter(name="wang").values("authordetail__tel")
print(ret)  # 結果:<QuerySet [{'authordetail__tel': '18971232312'}]>


(2)查詢手機號為13451222125的作者的名字 (正向查詢,按字段)

ret = AuthorDetail.objects.filter(tel="13451222125").values("author__name")
print(ret)  # 結果:<QuerySet [{'author__name': 'li'}]>


2、一對多關系


(1)查詢id=15的書籍的出版社的名稱(正向查詢,按字段)

ret = Book.objects.filter(id=15).values("publish__name")
print(ret)  # 結果:<QuerySet [{'publish__name': '上海出版社'}]>

(2)查詢天津出版社出版過的書籍名稱(反向查詢,按表名小寫)

ret = Publish.objects.filter(name="天津出版社").values("book__title")
print(ret)  # 結果:<QuerySet [{'book__title': 'go'}, {'book__title': '操作系統原理'}]>


3、多對多關系

(1)查詢(1)查詢書名為go的所有作者的名字(正向查詢,按字段)

ret = Book.objects.filter(title="go").values("author__name")
print(ret)  # 結果:<QuerySet [{'author__name': 'wang'}, {'author__name': 'zhang'}]>


(2)查詢zhang出版過的所有書籍名稱(反向查詢,按表名小寫)

ret = Author.objects.filter(name="zhang").values("book__title")
print(ret)  # 結果:<QuerySet [{'book__title': 'go'}, {'book__title': 'python'}, {'book__title': '操作系統原理'}, {'book__title': 'Linux'}]>


# 查詢手機號以1開頭的作者出版過的所有書籍名稱以及出版社名稱

ret=AuthorDetail.objects.filter(tel__startswith="189").values("author__book__title","author__book__publish__name")
print(ret)  #結果是:<QuerySet [{'author__book__title': 'go', 'author__book__publish__name': '天津出版社'}, {'author__book__title': 'css', 'author__book__publish__name': '上海出版社'}, {'author__book__title': '操作系統原理', 'author__book__publish__name': '天津出版社'}, {'author__book__title': 'Linux', 'author__book__publish__name': '河北出版社'}]>

四、聚合和分組

from django.db.models import Avg, Count, Max, Min


1、統計所有書籍的平均價格

ret = Book.objects.all().aggregate(c=Avg("price"))
print(ret)  # 結果是:{'c': 249.5}


2、查詢每一個出版社出版的書籍個數

ret = Publish.objects.all().annotate(c=Count("book")).values("name", "c")
print(ret)  # 結果是:<QuerySet [{'name': '北京出版社', 'c': 0}, {'name': '上海出版社', 'c': 2}, {'name': '天津出版社', 'c': 2}, {'name': '河北出版社', 'c': 1}, {'name': '唐山出版社', 'c': 1}]>


3、查詢每一個作者出版的書籍的平均價格

ret = Author.objects.all().annotate(price_avg=Avg("book__price")).values("name", "price_avg")
print(ret)  # 結果是:<QuerySet [{'name': 'song', 'price_avg': 252.25}, {'name': 'wang', 'price_avg': 230.0}, {'name': 'li', 'price_avg': 280.0}, {'name': 'zhang', 'price_avg': 280.0}, {'name': 'zhao', 'price_avg': None}, {'name': 'zhou', 'price_avg': None}]>


4、查詢每一本書籍名稱以及作者的個數

ret = Book.objects.all().annotate(author_num=Count("author")).values("title", "author_num")
print(ret)  # 結果是:<QuerySet [{'title': 'linux', 'author_num': 2}, {'title': 'css', 'author_num': 2}, {'title': 'go', 'author_num': 2}, {'title': '操作系統原理', 'author_num': 3}, {'title': 'Linux', 'author_num': 4}, {'title': 'python', 'author_num': 3}]>


5、查詢價格大於200的每一本書籍名稱以及作者的個數

ret = Book.objects.filter(price__gt=200).annotate(author_num=Count("author")).values("title", "author_num")
print(ret)  # 結果是:<QuerySet [{'title': 'linux', 'author_num': 2}, {'title': 'go', 'author_num': 2}, {'title': 'python', 'author_num': 3}, {'title': '操作系統原理', 'author_num': 3}, {'title': 'Linux', 'author_num': 4}]>

五、F查詢和Q查詢

from django.db.models import F,Q

1、F查詢

(1)查找comment_num數量大於poll_num的書

ret = Book.objects.filter(comment_num__gt=F("poll_num"))
print(ret)


(2)查找comment_num數量大於10倍的poll_num的書

ret = Book.objects.filter(comment_num__gt=F("read_num") * 10)
print(ret)


(3)把所有書的價格都加100

Book.objects.all().update(price=F("price") + 100)


2、Q查詢

(1)查找以Java開頭並且價格大於200的書

ret = Book.objects.filter(title__startswith="java", price__gt=200)
print(ret)


(2)查找以Java開頭或者價格小於200的書

ret = Book.objects.filter(Q(title__startswith="java") | Q(price__lt=200))
print(ret)


(3)查找2017年出版的Java開頭的書或者2017年的價格小於200的書

ret = Book.objects.filter(Q(title__startswith="java") | Q(price__lt=200), create_time__year=2017, )
print(ret)




Django之ORM跨表操作