1. 程式人生 > 實用技巧 >ORM多表更新刪除 查詢

ORM多表更新刪除 查詢

刪除和修改

一對一和一對多的操作

# 修改和刪除操作
def edit_book(request):
    # 一對一修改
    # 方式一: 通過模型類物件
    au_det_obj = models.AuthorDetail.objects.get(id=3)
    models.Author.objects.filter(id=1).update(name="bob",ad=au_det_obj)
    # # 方式二
    models.Author.objects.filter(id=5).update(name="jack",ad_id=1)

    # 一對多修改:同一對一
# 方式一: pub_obj = models.Publish.objects.get(id=2) models.Book.objects.filter(id=6).update(pud=pub_obj) # 方式二: models.Book.objects.filter(id=7).update(pud_id=3) # 刪除: 注意級聯刪除關係, 相關的資料都會刪掉 models.Author.objects.get(id=1).delete() models.Author.objects.filter(id=3).delete() models.AuthorDetail.objects.filter(id
=4).delete() return HttpResponse('OK')

多對多關係的刪除和更新

# 多對多的刪除和更新
    # 刪除remove
    book_obj = models.Book.objects.get(id=1)
    book_obj.authors.remove(8) # 刪除一條
    book_obj = models.Book.objects.get(id=6)
    book_obj.authors.remove(7, 8) # 刪除多條

    # 清空clear
    book_obj = models.Book.objects.get(id=4)
    book_obj.authors.clear()

    
# 更新 book_obj = models.Book.objects.get(id=3) book_obj.authors.set("7") # 引數是可迭代型別資料 # 更改多條 book_obj.authors.set([7,8,9]) # set動作有兩步:1 先執行clear 2 再執行add新增

多表查詢

基於物件的跨表查詢(子查詢)

正向查詢:關係屬性寫在哪個表裡面,那麼通過這個表的資料,去查詢關聯的另外一張表的資料,就叫做正向查詢,反之就是反向查詢

# 一對一正向查詢
    # 查陳六六作者的電話號碼
    author_obj = models.Author.objects.get(name="陳六六")
    # author_obj.ad 找到了author_obj關聯的作者詳細資訊表裡面對應記錄
    print(author_obj.ad.telephore) # 777
    # 反向查詢 : 反向查詢用關聯它的模型類的名稱小寫
    # 查詢地址為北京的作者名稱
    aut_det_obj = models.AuthorDetail.objects.get(address="四川")
    print(aut_det_obj.author.name) # 陳七七

    # 一對多正向查詢 同一對一查詢
    # 查詢人生是哪個出版社的
    book_obj = models.Book.objects.get(title="人生")
    print(book_obj.pud.name) # 小樹出版社
    # 反向查詢 模型類名小寫_set
    # 查詢小樹出版社出版哪些書
    pub_obj = models.Publish.objects.get(name="小樹出版社")
    print(pub_obj.book_set.all()) # <QuerySet [<Book: Book object>, <Book: Book object>]> 類似於objects控制器
    print(pub_obj.book_set.all().values("title")) # <QuerySet [{'title': '人生'}, {'title': '人類'}]>

    # 多對多查詢
    # 正向查詢 使用屬性來查
    # 查詢人生是誰寫的
    book_obj = models.Book.objects.get(title="人生")
    print(book_obj.authors.all().values("name"))
    # <QuerySet [{'name': '陳六六'}, {'name': '陳七七'}, {'name': '張三'}]>
    # 反向查詢 使用模型類名小寫_set
    # 查詢陳六六寫了哪些書
    author_obj = models.Author.objects.get(name="陳六六")
    print(author_obj.book_set.all().values("title"))
    # <QuerySet [{'title': '人間'}, {'title': '人生'}]>
    return HttpResponse('OK')

檢視原生SQL語句的方法

1 ORM語句.query
2 在settings配置檔案中寫上如下內容,就能夠自動打印出我們執行orm語句對應的sql語句 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }  3 通過django配置的連線mysql的管道來檢視(pymysql) from app01 import models def add_book(request): ''' 新增表記錄 :param request: http請求資訊 :return: ''' book_obj = models.Book(title='python',price=123,pub_date='2012-12-12',publish='人民出版社') book_obj.save() from django.db import connection #通過這種方式也能檢視執行的sql語句 print(connection.queries) return HttpResponse('ok')

基於雙下滑線的跨表查詢(連表操作)

# 一對一正向查詢  使用屬性
    # 查詢陳七七作者的地址
    res = models.Author.objects.filter(name="陳七七").values("ad__address")
    print(res) # <QuerySet [{'ad__address': '四川'}]>
    # 反向查詢 表名小寫
    res = models.AuthorDetail.objects.filter(author__name="陳七七").values("address")
    print(res) # <QuerySet [{'address': '四川'}]>

    # 一對多正向查詢
    # 查詢人世是哪個出版社的
    res = models.Book.objects.filter(title="人世").values("pud__name")
    print(res) # <QuerySet [{'pud__name': '小草出版社'}]>
    # 反向操作
    res = models.Publish.objects.filter(book__title="人世").values("name")
    print(res) # <QuerySet [{'name': '小草出版社'}]>

    # 多對多正向查詢 使用關聯屬性
    # 查詢人類這本書是誰寫的
    res = models.Book.objects.filter(title="人類").values("authors__name")
    print(res) # <QuerySet [{'authors__name': 'jack'}]>
    # 反向查詢
    res = models.Author.objects.filter(book__title="人類").values("name")
    print(res) # <QuerySet [{'name': 'jack'}]>

聚合查詢(aggregate)

# 聚合查詢
    from django.db.models import Max, Min, Avg, Count, Sum
    # 統計一下所有書籍的平均價格
    res = models.Book.objects.aggregate(Avg("price"))
    print(res) # {'price__avg': 62.757143}  結果是普通字典型別
    # 可以起別名
    res = models.Book.objects.aggregate(a=Avg("price"),b=Max("price"))
    print(res) # {'a': 62.757143, 'b': Decimal('99.90')}
    # aggregate方法可以看為是orm語句的結束語句,結果為普通字典型別,不能在繼續呼叫queryset或者模型類物件提供的方法了

分組查詢(annotate)

# 分組查詢 必須制定別名
    # 查詢一下每個出版社出版書的平均價格
    from django.db.models import Max, Min, Avg, Count, Sum
    res = models.Book.objects.values("pud_id").annotate(a=Avg("price"))
    print(res)
    # <QuerySet [{'pud_id': 1, 'a': 99.9}, {'pud_id': 2, 'a': 39.9}, {'pud_id': 3, 'a': 59.9}]>
    res = models.Book.objects.values("pud_id","id").annotate(a=Avg("price"))
    print(res) # values裡面可以加多個分組條件
    # 以出版社名稱分組的書的平均價格
    res = models.Book.objects.values("pud__name").annotate(a=Avg("price"))
    print(res)
    # <QuerySet [{'pud__name': '小草出版社', 'a': 39.9}, {'pud__name': '小樹出版社', 'a': 59.9}, {'pud__name': '小花出版社', 'a': 99.9}]>

    res = models.Publish.objects.annotate(a=Avg("book__price"))
    print(res)
    # <QuerySet [<Publish: Publish object>, <Publish: Publish object>, <Publish: Publish object>]>
    # 返回結果是Publish的模型類物件,這個模型類物件裡面包含Publish的所有屬性資料,還有annotate的統計結果資料
    ret = res.values("name","a")
    print(ret)
    # <QuerySet [{'name': '小草出版社', 'a': 39.9}, {'name': '小樹出版社', 'a': 59.9}, {'name': '小花出版社', 'a': 99.9}]>

F查詢:主要是針對本表的多個欄位進行比較時使用

# F查詢
    # F查詢可以用來做本表不同欄位之間的一個比較
    # 查詢點贊數大於評論數的書籍
    from django.db.models import F
    res = models.Book.objects.filter(dianzan__gt=F("comment"))
    print(res)
    # <QuerySet [<Book: 人間>, <Book: 人生>, <Book: 人類>]>
    # F可以用來對本表資料進行一些統一操作(四則運算都支援)
    # 將所有的書籍上調10塊錢
    models.Book.objects.all().update(price=F("price")+10)

Q查詢:可以進行多條件查詢,查詢關係可以是 或與非

# Q查詢  filter中的查詢條件預設是and關係
    # 可以進行多條件查詢,查詢關係可以是 或與非
    from django.db.models import Q
    # ~ 條件取反 ,&--and關係 ,|--or關係
    # 查詢書名中包含以小開頭的,或者評論數在350以上的
    res = models.Book.objects.filter(Q(title__startswith="")|Q(comment__gt=350))
    print(res)
    # <QuerySet [<Book: 小貓>, <Book: 貓生>, <Book: 小狗>]>

    # 查詢書名中包含小的,或者評論數在350以上的,並且點贊數大於400的
    res = models.Book.objects.filter(Q(title__startswith="")|Q(comment__gt=350),dianzan__gt=400)
    print(res) # <QuerySet [<Book: 貓生>, <Book: 小狗>]>
    # 注意,如果結合逗號來進行and的關係查詢,那麼必須將沒有Q包裹的查詢條件放在Q包裹的查詢條件後面

    #下面這種方式也可以,Q查詢可以多層巢狀使用
    res = models.Book.objects.filter(Q(title__startswith="") | Q(comment__gt=350)&Q( dianzan__gt=400))
    print(res) # <QuerySet [<Book: 小貓>, <Book: 貓生>, <Book: 小狗>]>