ORM查詢操做

ORM查詢操做

一、如何只單獨測試Django中的某一個py文件

在應用下的tests文件或者新建任意一個py文件中書寫如下代碼:python

# 在manage.py文件中複製過來
import os
​
if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mypoject.settings")
    #手寫導入django模塊
    import django
    django.setup()

二、單表查詢之必知必會16條

一、create()

給表添加數據,返回值就是當前被建立數據的對象自己數據庫

from app01 import models
res = models.Movie.objects.create(title='西遊記', price=999.99)
print(res)  # Movie object   

二、all()

查詢表中全部的數據,返回值是queryset對象,而且,只要返回值是queryset對象就可使用對象 點query 的方式查看獲取到的內部SQL語句django

    res = models.Movie.objects.all()
    print(res)  # <QuerySet [<Movie: Movie object>, <Movie: Movie object>]>
    print(res.query)
    # SELECT `app01_movie`.`id`, `app01_movie`.`title`, `app01_movie`.`price`, `app01_movie`.`publish_time` FROM `app01_movie`

三、filter()

不傳參數就是查詢全部,傳參數就是查詢指定的數據,返回值是列表套queryset對象,當查詢對象不存在時,不會報錯app

pk 就是指當前的主鍵字段名函數

    res = models.Movie.objects.filter()  # 不傳參數就是查全部對象
    print(res)  # <QuerySet [<Movie: Movie object>, <Movie: Movie object>]>
    # pk 就是指當前的主鍵字段名
    res1 = models.Movie.objects.filter(pk=1, title='西遊記')  # 能夠傳多個參數是以and鏈接
    print(res1)  # <QuerySet [<Movie: Movie object>]>

四、update()

更新數據,先查出數據再更新,返回值是受影響的行數測試

    res = models.Movie.objects.filter(pk=1).update(title='水滸傳')
    print(res)  # 1

五、delete()

刪除數據,先查出要刪除的數據,再刪除,返回值是受影響的表和行數 (1, {'app01.Movie': 1})spa

    res = models.Movie.objects.filter(pk=3).delete()
    print(res)  # (1, {'app01.Movie': 1})

六、first()

先獲取到數據對象,取第一個元素code

    res = models.Movie.objects.filter().first()
    print(res)  # Movie object
    print(res.title)  # 西遊記
    # 由於經過主鍵只獲取到一條數據,全部查第一個就是pk=1的數據
    res = models.Movie.objects.filter(pk=1).first()
    print(res)  # Movie object
    print(res.title)  # 西遊記

七、last()

先獲取到數據對象,取最後一個元素對象

    res = models.Movie.objects.filter().last()
    print(res)  # Movie object
    print(res.title, res.price)  # 東遊記 888.88
    # 由於經過主鍵只獲取到一條數據,全部查最後一個就是pk=1的數據
    res = models.Movie.objects.filter(pk=1).last()
    print(res)  # Movie object
    print(res.title, res.price)  # 西遊記 999.99

八、get()

返回值是直接獲取對象自己,當查詢條件不存在時會報錯,而且必需要傳一個參數,不推薦使用blog

    res = models.Movie.objects.get(pk=1)
    print(res)

九、values()

獲取queryset對象是 [{},{}] 不傳參數就是獲取全部,傳參數能夠指定獲取對應的字段數據

    res = models.Movie.objects.values()
    print(res)
    # <QuerySet [{'id': 1, 'title': '西遊記', 'price': Decimal('999.99'), 'publish_time': datetime.date(2014, 1, 8)}, {'id': 2, 'title': '東遊記', 'price': Decimal('888.88'), 'publish_time': datetime.date(2011, 1, 8)}]>
    res = models.Movie.objects.values('title', 'price')
    print(res)
    # <QuerySet [{'title': '西遊記', 'price': Decimal('999.99')}, {'title': '東遊記', 'price': Decimal('888.88')}]>

十、values_list()

獲取queryset對象是 [(,)(,)] 不傳參數就是獲取全部,傳參數能夠指定獲取對應的字段數據

    res = models.Movie.objects.values_list()
    print(res)
    res = models.Movie.objects.values_list('title')
    print(res)  # <QuerySet [('西遊記',), ('東遊記',)]>

十一、order_by()

按照指定字段進行排序,返回queryset對象,對數據庫不進行修改

    # 默認升序
    res = models.Movie.objects.order_by('price')
    print(res)
    # 減號就是降序
    res = models.Movie.objects.order_by('-price')
    print(res)

十二、count()

統計數據總共有多少條,不能指定參數統計

    res = models.Movie.objects.count()
    print(res)  # 2

1三、exclude()

排除什麼以外,返回值是排除以外的全部數據

    res = models.Movie.objects.exclude(pk=1)
    # 排除主鍵是1以外的數據
    print(res)

1四、exists()

返回值是布爾值,判斷當前對象是否有數據,返回值是布爾值

    res = models.Movie.objects.filter(pk=21).exists()
    print(res) # False

1五、reverse()

反轉數據,將原排序後的數據反轉

    res = models.Movie.objects.order_by('price').reverse()
    print(res)

1六、distinct()

去重,去重的前提是必需要有兩個數據徹底同樣才能夠,通常有主鍵,都不會徹底同樣的

    res = models.Movie.objects.values('title').distinct()
    # 因爲有主鍵,不徹底同樣,全部不會去重
    print(res)

三、單表查詢之神奇的下劃線查詢

一、查詢價格大於200的電影:price__gt 大於 gt

    # 1.查詢價格大於200的電影
    res = models.Movie.objects.filter(price__gt=200)
    print(res)

二、查詢價格小於900的電影 : price__lt 小於 lt

    res = models.Movie.objects.filter(price__lt=900)
    print(res)

三、查詢價格大於等於888.88的電影:price__gte 大於等於 gte

    res = models.Movie.objects.filter(price__gte=888.88)
    print(res)

四、查詢價格小於等於999.99的電影:price__lte 小於等於 lte

因爲python對小數不是很敏感,全部小數有可能會不會精確找到,最好定義用整數

    res = models.Movie.objects.filter(price__lte=999.99)
    print(res)

五、查詢價格是888或999的數據:price__in=[888,999] 注意是列表

因爲正經常使用filter查詢多個時是and關係,因此可使用雙下劃線的方式

    res = models.Movie.objects.filter(price__in=[888,999])
    print(res)

六、查詢價格在800到900之間 電影數據,顧頭也顧尾 price__range=(800,900),注意是小括號

    res = models.Movie.objects.filter(price__range=(800,900))
    print(res)

七、查詢電影名中包含字母L的電影

  __contains 是區分大小寫的

  __icontains 是不區分大小寫的

    res = models.Movie.objects.filter(title__contains='l')
    print(res)  # <QuerySet [<Movie: 東遊記l>]>
    res = models.Movie.objects.filter(title__icontains='l')
    print(res)  # <QuerySet [<Movie: 東遊記L>, <Movie: 東遊記l>]>

八、查詢2014年、月、日出版的電影 __ year __ day __ month

    res = models.Movie.objects.filter(publish_time__year=2014)
    print(res)
    res = models.Movie.objects.filter(publish_time__month=1)
    print(res)
    res = models.Movie.objects.filter(publish_time__day=8)
    print(res)

四、多表查詢以外鍵字段的增刪改查

一、一對多

    # 增:方法一:直接寫實際的字段publish_id
    models.Book.objects.create(name='紅樓夢', price=888, store=500, sell=800, publish_id = 3)  # publish_id真實表中的的字段
    # 增:方法二:先get方法拿到出版社對象,再給書加對應的出版社
    publish_obj = models.Publish.objects.get(pk=2)
    models.Book.objects.create(name='三體', price=888, store=600, sell=800, publish = publish_obj)  # publish自定義時的字段
    # 改:1.直接指名道姓的修改
    models.Book.objects.filter(pk=9).update(publish_id=3)
    publish_obj = models.Publish.objects.get(pk=1)
    models.Book.objects.filter(pk=9).update(publish=publish_obj)
    # 刪除:外鍵字段在1.x版本默認就是級聯更新級聯刪除,2.x版本須要手動指定

二、多對多

  一、綁定關係:add

add專門給第三張表添加數據,括號內既能夠傳數字也能夠傳對象,而且支持傳多個

    # 多對多
    #給書籍綁定做者關係
    # 方式一:
    # 1.拿到書對象
    book_obj = models.Book.objects.filter(pk=3).first()
    # 2.書籍對象點虛擬字段authors就跳到第三張表中了,再add綁定
    book_obj.authors.add(1)
    book_obj.authors.add(2,3)  # 能夠支持一本書綁定多個做者
# 方式二
    # 1.拿到書籍對象
    book_obj = models.Book.objects.filter(pk=5).first()
    # 2.經過get方法拿到做者對象
    author_obj = models.Author.objects.get(pk=1)
    # 3.給書籍對象點虛擬的authors跳轉到第三張表,add對象添加數據
    book_obj.authors.add(author_obj)

  二、移除關係:remove

remove專門給第三張表移除數據,括號內便可以傳數字也能夠傳對象,而且都支持多個

    # 方式一:
    # 1.拿到書對象
    book_obj = models.Book.objects.filter(pk=3).first()
    # 2.書籍對象點虛擬字段authors就跳到第三張表中了,再remove移除關係
    book_obj.authors.remove(1)
    book_obj.authors.remove(2,3)  # 能夠支持一本書傳多個參數移除關係
# 方式二
    # 1.拿到書籍對象
    book_obj = models.Book.objects.filter(pk=5).first()
    # 2.經過get方法拿到做者對象
    author_obj = models.Author.objects.get(pk=1)
    # 3.給書籍對象點虛擬的authors跳轉到第三張表,remove移除關係
    book_obj.authors.remove(author_obj)

  三、修改關係:set

修改兩張表的關係,括號內支持傳數字和對象,可是須要是可迭代對象,能夠set中是元組或者列表

    # 方式一:
    # 1.拿到書對象
    book_obj = models.Book.objects.filter(pk=3).first()
    # 2.書籍對象點虛擬字段authors就跳到第三張表中了,再set設置關係
    book_obj.authors.set((3,))
    book_obj.authors.set((1,3))  # 能夠支持一本書傳多個參數設置關係
# 方式二
    # 1.拿到書籍對象
    book_obj = models.Book.objects.filter(pk=5).first()
    # 2.經過get方法拿到做者對象
    author_obj = models.Author.objects.get(pk=1)
    # 3.給書籍對象點虛擬的authors跳轉到第三張表,set設置關係
    book_obj.authors.set([author_obj])

  四、清空關係:clear

清空第三張表的數據,不須要傳任意參數

    # 清空第三表中書的id是5的數據
    book_obj = models.Book.objects.filter(pk=5).first()
    book_obj.authors.clear()

五、多表查詢之跨表查詢

跨表查詢的方式:子查詢和鏈表查詢

正向和反向的概念:

  正向:跨表查詢的時候 外鍵字段是否在當前數據對象中,若是在查詢另外一張表關係,叫作正向

  反向:若是外鍵字段不在當前的數據對象中,叫作反向

口訣:正向查詢按外鍵字段若是有多個對應加.all(),反向查詢按表名小寫,若是有多個對應加_set.all()

一、基於對象的跨表查詢(子查詢)

將一張表的查詢結果當作另一張表的查詢條件,分佈操做

    # 1.查詢書籍pk爲5的出版社名稱  正向按照外鍵字段
    book_obj = models.Book.objects.filter(pk=5).first()
    print(book_obj.publish)  # Publish object
    print(book_obj.publish.name)  # 東方出版社
    print(book_obj.publish.addr)  # 東京
    
    #2. 查詢書籍pk爲3的做者的名字  正向按照外鍵字段
    book_obj = models.Book.objects.filter(pk=3).first()
    print(book_obj.authors.all())  # 有多個的時候須要用all
    author_list = book_obj.authors.all()
    for author_obj in author_list:
        print(author_obj.name)
        
    # 3.查詢做者pk爲1的電話號碼  正向按照外鍵字段
    author_obj = models.Author.objects.filter(pk=1).first()
    print(author_obj.author_detail)  # 只有一個對應就不須要用all
    print(author_obj.author_detail.phone)
    
    # 4.查詢出版社名稱爲東方出版社出版的書  反向按照表名小寫
    publish_obj = models.Publish.objects.filter(name='東方出版社').first()
    print(publish_obj.book_set.all())  # 有多條對應就要用_set.all()
    
    # 5.查詢做者爲Jason寫過的書
    author_obj = models.Author.objects.filter(name='Jason').first()
    print(author_obj.book_set.all())  # 有多個數據時要加_set.all()
    
    # 6.查詢手機號爲120的做者姓名
    author_detail_obj = models.AuthorDetail.objects.filter(phone=120).first()
    print(author_detail_obj.author)  # 反向按照表名小寫
    print(author_detail_obj.author.name)

二、基於雙下劃線的跨表查詢(鏈表查詢)

只要表之間有關係,就能夠經過正向的外鍵字段或反向的表名小寫,連續跨表操做獲取對應的數據

    # 1.查詢書籍pk爲3的出版社名稱
    # 正向
    res = models.Book.objects.filter(pk=3).values('publish__name')
    print(res)
    # 反向
    # res = models.Publish.objects.filter(book__pk=3)  # 拿pk爲3的書對應的出版社對象
    res = models.Publish.objects.filter(book__pk=3).values('name')
    print(res)
    
    # 2.查詢書籍pk爲3的做者名和年齡
    # 正向
    res = models.Book.objects.filter(pk=3).values('authors__name', 'authors__age','name')
    print(res)
    # 反向
    # res = models.Author.objects.filter(book__pk=3)  # 拿到書籍pk=3的做者對象
    res = models.Author.objects.filter(book__pk=3).values('name', 'age', 'book__name')
    print(res)
    
    # 3.查詢做者是Jason的年齡和手機號
    # 正向
    res = models.Author.objects.filter(name='Jason').values('author_detail__phone', 'age')
    print(res)
    # 反向
    res = models.AuthorDetail.objects.filter(author__name='Jason').values('phone','author__age')
    print(res)
    
    # 4. 查詢書籍pk爲3的的做者手機號
    # 正向
    res = models.Book.objects.filter(pk=3).values('authors__author_detail__phone')
    print(res)
    # 反向
    res = models.AuthorDetail.objects.filter(author__book__pk=3).values('phone')
    print(res)

六、聚合查詢

一、首先須要導入聚合函數

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

二、關鍵字:aggregate

    from django.db.models import Max, Min, Sum, Count, Avg
    # 查詢全部書的平均價格
    res = models.Book.objects.aggregate(avg_num=Avg('price'))  # avg_num是變量名,可不用
    print(res)
​
    # 查詢全部書中最貴的書
    res = models.Book.objects.aggregate(max_num=Max('price'))
    print(res)
​
    # 所有使用
    res = models.Book.objects.aggregate(Min('price'), Count('pk'), Sum('price'))
    print(res)

七、分組查詢

關鍵字:annotate

    from django.db.models import Max, Min, Sum, Count, Avg
    # 1.統計每一本書的做者個數
    # res = models.Book.objects.annotate(author_num=Count('authors')).values('name')
    res = models.Book.objects.annotate(author_num=Count('authors'))
    print(res)
    # 2.統計每一個出版社賣的最貴的書
    res= models.Publish.objects.annotate(max_price=Max('book__price')).values('name', 'book__name', 'book__price')
    print(res)
    # 3.統計不止一個做者的圖書
    res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('name')
    print(res)
    # 4.查詢各個做者的書的總價格
    res = models.Author.objects.annotate(price_sum=Sum('book__price')).values('name', 'price_sum')
    print(res)

八、F與Q查詢

F:能夠獲取表中的某個字段對應的值

Q:可以改變查詢的條件關係,and or not

首先須要導入F和Q模塊

from django.db.models import F, Q
    from django.db.models import F, Q
    # 1.查詢全部庫存小於賣出的書
    res = models.Book.objects.filter(store__lt=F('sell'))
    print(res)
    # 2.將全部的書價格提升100
    res = models.Book.objects.update(price=F('price')+100)  # 直接對數據庫進行操做
    
    # 查詢書的名字是西遊記或者價格是888的書
    res = models.Book.objects.filter(name='西遊記', price=888)  # and關係
    res = models.Book.objects.filter(Q(title='西遊記'),Q(price=1000))  # 逗號是and關係
    res = models.Book.objects.filter(Q(title='西遊記')|Q(price=1000))  # |是or關係
    res = models.Book.objects.filter(~Q(title='西遊記')|Q(price=1000))  # ~是not關係

# Q的高階用法 # res = models.Book.objects.filter('title'='python入門') ​ q = Q() q.connector = 'or' # q對象默認也是and關係 能夠經過connector改變or q.children.append(('title','python入門')) q.children.append(('price',1000)) ​ res = models.Book.objects.filter(q) print(res)
相關文章
相關標籤/搜索