Django之表高級操做

1、如何開啓本身的測試腳本?

如何只單獨測試django中的某一個py文件
    如何書寫測試腳本
    
    在任意一個py文件中書寫如下代碼 
        應用下的tests
        或者本身新建一個
        
        
    import os
    if __name__ == "__main__":
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings")
        import django
        django.setup()

這樣就能夠直接運行你的test.py文件來運行測試mysql

2、對錶數據的添加、更新、刪除

1.create()      # 添加
2.update()      # 更新
3.delete()      # 刪除

1.create()

# 對電影表添加一條數據
# create()  返回值就是當前被建立數據的對象自己
models.Movie.objects.create(title='西遊記',price=999.23,publish_time='2016-1-1')


 # 還能夠直接傳日期對象
    from datetime import date
    ctime = date.today()
    models.Movie.objects.create(title='西遊記', price=666.23, publish_time=ctime)

2.update()

# update()  更新數據      返回值是受影響的行數
res = models.Movie.objects.filter(pk=1).update(title='玉女心經')
print(res)  # 1   受影響的條數

3.delete()

# delete()  刪除數據    返回值(1, {'app01.Movie': 1})  受影響的表及行數
res = models.Movie.objects.filter(pk=3).delete()
print(res)  # (1, {'app01.Movie': 1})

4.查看執行的sql語句

res = models.Movie.objects.filter(pk=3).delete()
print(res.query)  # 獲取res的sql執行語句

3、 單表查詢13個操做

返回QuerySet對象的方法有:
            all()
            filter()
            exclude()
            order_by()
            reverse()
            distinct()
特殊的QuerySet:
            values()       返回一個可迭代的字典序列
            values_list()  返回一個可迭代的元組序列
返回具體對象的:
            get()
            first()
            last()  
返回布爾值的方法有:
            exists()
返回數字的方法有:
            count()

返回QuerySet對象的方法有:

1.all() 查詢全部結果

res = models.Movie.objects.all()
print(res)

2.filter() 條件匹配

# 獲取電影表中id爲1的數據
# 不存在就返回空,而不是報錯。get(id=1)不存在就直接報錯
res = models.Movie.objects.filter(id=1)
print(res)

3.exclude() 取反

# 獲取id爲1以外的數據
res = models.Movie.objects.exclude(pk=1)
print(res)

4.order_by() 排序

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

5.reverse() 反轉

res = models.Movie.objects.order_by('price').reverse()  # 將次序反轉

6.distinct() 去重

# 去重:去重的前提 必須是由徹底同樣的數據的才能夠
res = models.Movie.objects.values('title','price').distinct()

特殊的QuerySet:

7.values() 獲取指定字段對 列表套字典

返回一個可迭代的字典序列sql

values(*field): 返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列model的實例化對象,而是一個可迭代的字典序列django

# values()   QuerySet對象  [{},{},{}]     獲取指定字段對的數據
# 返回一個可迭代的字典序列
res = models.Movie.objects.values('title','publish_time')

8.values_list() 獲取指定字段對** 列表套字典 列表套元組

返回一個可迭代的元組序列app

values_list(*field): 它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列測試

res = models.Movie.objects.values_list('title','price')
print(res)

返回具體對象的:

9.get 直接獲取對象,不存在就報錯

# get()      直接獲取對象自己  不推薦使用  當查詢條件不存在的時候直接報錯
res = models.Movie.objects.get(pk=1)
print(res)

10.first() 取第一個元素對象

# first()    數據對象        取第一個元素對象
res = models.Movie.objects.filter().first()
print(res)

11.last() 取最後一個元素對象

# last()    數據對象          取最後一個元素對象
res = models.Movie.objects.last()
print(res)

返回布爾值的方法有:

12.exists()

# exists()   返回的是布爾值  判斷前面的對象是否有數據
res = models.Movie.objects.filter(pk=1000).exists()  # 不存在,Fslse
print(res)

res = models.Movie.objects.filter(pk=1).exists()   # 存在,True

返回數字的方法有:

13.count() 統計數據條數

# 統計篩選以後數據的條數
res = models.Movie.objects.count()
print(res)

4、雙下線查詢

在python中咱們進行邏輯判斷會用到>、<、=、or之類的符號,那麼在Django進行models數據操做的時候,咱們表示:雙下劃線code

__gt        : 大於
__lt        : 小於
__gte       : 大於等於
__lte       : 小於等於
__in        : 或
__rang      : 在...之間,顧頭也顧尾
__contains   :模糊查詢,區分大小寫
__icontains  :模糊查詢,不區分大小寫
__year      : 查詢年份
__month     : 查詢月份

案例:對象

# 神奇的雙下劃線查詢
    # 1.查詢價格大於200的電影
    res = models.Movie.objects.filter(price__gt=200)
    print(res)
    # 2.查詢價格小於500的電影
    res = models.Movie.objects.filter(price__lt=500)
    print(res)
    # 3.查詢價格大於等於876.23的電影
    res = models.Movie.objects.filter(price__gte=876.23)
    print(res.query)
    # 4.查詢價格小於等於876.23的電影
    res = models.Movie.objects.filter(price__lte=500)
    print(res)
    # 5.查詢價格是123 或666 或876
    res = models.Movie.objects.filter(price__in=[123,666,876])
    print(res)
    # 6.查詢價格在200到900之間的電影  顧頭也顧尾
    res = models.Movie.objects.filter(price__range=(200,900))
    print(res)
    # 7.查詢電影名中包含字母p的電影
    res = models.Movie.objects.filter(title__contains='p')  # 默認是區分大小寫
    res = models.Movie.objects.filter(title__icontains='p')  # i忽略大小寫
   
    # 8.查詢2014年出版的電影
    res = models.Movie.objects.filter(publish_time__year=2014)
    # print(res)
    # 9.查詢是1月份出版的電影
    res = models.Movie.objects.filter(publish_time__month=1)
    print(res)

5、外鍵字段的增刪改查

在1.X版本中默認就是級聯更新、級聯刪除blog

在2.X版本中須要本身手動設定排序

1.一對多

1.增 直接寫真實的表字段

# publish_id是外鍵字段
models.Book.objects.create(title='三國演義',price=123.23,publish_id=2)

2.增 經過對象

# Publish 是modles中有關聯的表
publish_obj = models.Publish.objects.get(pk=1)
models.Book.objects.create(title='大話西遊',price=66.66,publish=publish_obj)

1.改 直接篩選出來,直接改

models.Book.objects.filter(pk=1).update(publish_id=3)

2.改 經過對象

# 先獲取出版社表id爲4的對象
publish_obj = models.Publish.objects.get(pk=4)
models.Book.objects.filter(pk=1).update(publish=publish_obj)

2.多對多

1.綁定關係 add

add專門給第三張關係表添加數據
    括號內便可以傳數字也能夠傳對象  而且都支持傳多個
# 1.獲取書籍對象
book_obj = models.Book.objects.filter(pk=1).first()
# 2.書籍對象點‘.’外鍵字段就已經跨入第三張表中了。再用add添加綁定關係
book_obj.authors.add(1,2,3)  # 給書籍綁定一個主鍵爲1,2,3的做者
# 獲取對象
    author_obj = models.Author.objects.get(pk=1)
    author_obj1 = models.Author.objects.get(pk=3)
    # 添加綁定關係
    book_obj.authors.add(author_obj)
    book_obj.authors.add(author_obj,author_obj1)

2.移除綁定關係 remove

remove專門給第三張關係表移除數據
        括號內便可以傳數字也能夠傳對象  而且都支持傳多個
# 按照具體外鍵的值進行刪除
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.remove(2)
    book_obj.authors.remove(1,3)
    
    # 獲取相關對象刪除
    author_obj = models.Author.objects.get(pk=2)
    author_obj1 = models.Author.objects.get(pk=3)
    book_obj.authors.remove(author_obj)
    book_obj.authors.remove(author_obj,author_obj1)

3.修改綁定關係 set

set 修改書籍與做者的關係 
        括號內支持傳數字和對象 可是須要是可迭代對象
# authors外鍵字段,Author類名
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.set((3,))
book_obj.authors.set((2,3))


author_obj = models.Author.objects.get(pk=2)
author_obj1 = models.Author.objects.get(pk=3)
book_obj.authors.set([author_obj,author_obj1])   # 可迭代對象

4.清空關係

clear()  清空關係
    不須要任何的參數
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.clear()  # 去第三張表中清空書籍爲1的全部數據

6、跨表查詢

mysql中跨表查詢的方式
        1.子查詢  將一張表的查詢結果當作另一張表的查詢條件
            正常解決問題的思路 分步操做
        2.鏈表查詢
            inner join
            left join
            right join
            union
正反向的概念
        正向
            跨表查詢的時候 外鍵字段是否在當前數據對象中 若是在
            查詢另一張關係表  叫正向
            
        反向
            若是不在叫反向
        
        口訣
            正向查詢按外鍵字段
            反向查詢按表名小寫

案例:

正向查詢的時候 當外鍵字段對應的數據能夠有多個的時候須要加.all()
    不然點外鍵字典便可獲取到對應的數據對象
基於對象的反向查詢 表名小寫是否須要加_set.all()
        一對多和多對多的時候須要加
        一對一不須要

1.基於對象的跨表查詢(子查詢):

# 1.查詢書籍pk爲1的出版社名稱
    book_obj = models.Book.objects.filter(pk=1).first()
    print(book_obj.publish.name)
# 2.查詢書籍pk爲2的全部做者的姓名
    book_obj = models.Book.objects.filter(pk=2).first()
    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.phone)
 
# 4.查詢出版社名稱爲東方出版社出版過的書籍
    publish_obj = models.Publish.objects.filter(name='東方出版社').first()
    print(publish_obj.book_set.all())
    
# 5.查詢做者爲jason寫過的書
    author_obj = models.Author.objects.filter(name='jason').first()
    print(author_obj.book_set.all())
    
# 6.查詢手機號爲120的做者姓名
    author_detail_obj = models.AuthorDetail.objects.filter(phone=120).first()
    print(author_detail_obj.author.name)

2.基於雙下劃線跨表查詢(鏈表查詢)

只要表之間有關係  你就能夠經過正向的外鍵字段或者反向的表名小寫 連續跨表操做
# 1.查詢書籍pk爲1的出版社名稱
    # 正向
    res = models.Book.objects.filter(pk=1).values('publish__name')  # 寫外鍵字段 就意味着你已經在外鍵字段管理的那張表中
    print(res)
    # 反向
    res = models.Publish.objects.filter(book__pk=1)  # 拿出版過pk爲1的書籍對應的出版社
    res = models.Publish.objects.filter(book__pk=1).values('name')
    print(res)

# 2.查詢書籍pk爲1的做者姓名和年齡
    # 正向
    res = models.Book.objects.filter(pk=1).values('title','authors__name','authors__age')
    print(res)
    # 反向
    res = models.Author.objects.filter(book__pk=1)  # 拿出出版過書籍pk爲1的做者
    res = models.Author.objects.filter(book__pk=1).values('name','age','book__title')
    print(res)
    
# 3.查詢做者是jason的年齡和手機號
    # 正向
    res = models.Author.objects.filter(name='jason').values('age','author_detail__phone')
    print(res)
    # 反向
res = models.AuthorDetail.objects.filter(author__name='jason')  # 拿到jason的我的詳情
res = models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__age')
print(res)

# 4.查詢書籍pk爲的1的做者的手機號
    # 正向
    # 只要表之間有關係  你就能夠經過正向的外鍵字段或者反向的表名小寫 連續跨表操做
    res = models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
    print(res)
    # 反向
    res = models.AuthorDetail.objects.filter(author__book__pk=1).values('phone')
    print(res)

3.聚合查詢

須要使用到:aggregate關鍵字
from django.db.models import Max,Min,Avg,Count,Sum   # 導入模塊

res = models.Book.objects.aggregate(avg_num=Avg('price'))
print(res)
# 查詢價格最貴的書
res = models.Book.objects.aggregate(max_num=Max('price'))
print(res)
# 所有使用一遍
res = models.Book.objects.aggregate(Avg("price"), Max("price"), Min("price"),Count("pk"),Sum('price'))
print(res)

4.分組查詢

須要使用到:annotate關鍵字
# 1.統計每一本書的做者個數
    res = models.Book.objects.annotate(author_num=Count('authors')).values('title','author_num')
    print(res)

    # 2.統計出每一個出版社賣的最便宜的書的價格
    res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price','book__title')
    print(res)

    # 3.統計不止一個做者的圖書
    res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('title')
    print(res)

    # 4.查詢各個做者出的書的總價格
    res = models.Author.objects.annotate(price_sum=Sum('book__price')).values('name','price_sum')
    print(res)

如何按照表中的某一個指定字段分組?

res = models.Book.objects.values('price').annotate()  就是以價格分組

5.F查詢

在上面全部的例子中,咱們構造的過濾器都只是將字段值與某個咱們本身設定的常量作比較。若是咱們要對兩個字段的值作比較,那該怎麼作呢?

Django 提供 F() 來作這樣的比較。F() 的實例能夠在查詢中引用字段,來比較同一個 model 實例中兩個不一樣字段的值。

簡而言之:F()查詢能夠動態獲取表字段對應的值

須要導入模塊:from django.db.models import F,Q

案例:

# 1.查詢庫存數大於賣出數的書籍
    res = models.Book.objects.filter(kucun__gt=F('maichu'))
    print(res)

# 2.將全部書的價格提升100
    res = models.Book.objects.update(price=F('price') + 100)

6.Q查詢

','逗號隔開是and關係
'|'管道符是or的關係
'~'是not關係

filter() 等方法中逗號隔開的條件是與的關係。 若是你須要執行更復雜的查詢(例如OR語句),你可使用Q對象

示例1:

查詢 賣出數大於100 或者 價格小於100塊的

from django.db.models import Q
models.Product.objects.filter(Q(maichu__gt=100)|Q(price__lt=100))
# 1.查詢書的名字是python入門或者價格是1000的書籍
    res = models.Book.objects.filter(title='python入門',price=1000)  # and關係
    res = models.Book.objects.filter(Q(title='python入門'),Q(price=1000))  # 逗號是and關係
    res = models.Book.objects.filter(Q(title='python入門')|Q(price=1000))  # |是or關係
    res = models.Book.objects.filter(~Q(title='python入門')|Q(price=1000))  # ~是not關係

7.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)
相關文章
相關標籤/搜索