Django之ORM數據查詢方式練習

單表查詢

單表查詢簡單示例python

# 字段
models.DateField(auto_now_add)
models.DateField(auto_now)
# auto_now 和auto_now_add 都是兩個字段可使用的參數
	# auto_now: 每次操做該數據的增刪改查都會自動更新時間
    # auto_now_add: 新增數據的時候,會建立時間,後期在作修改的時候,不更新時間
# 新增數據

if  __name__=="__main__":
    os.envron.setdefault('....')
    import django
    django.setup()
    from app01 import models
    
    
    # 新增數據
    # 基於create
    user_obj= models.User.objects.create(name='qzk',age=18,register_time='2019-1-1')
    # 基於對象的綁定方法
    import datetime
    ctime= datetime.datetime.now()
    user_obj= models.User(name='qby',age=18,register_time=ctime)
    user_obj.save()
    
    
    # 修改數據
    # 基於對象的綁定方法
    user_obj = models.User.objects.filter(name='qzk').first()
    user_obj.age=19
    user_obj.save()
    # 基於queryset
    models.User.objdects.filter(name='kevin').update(age=66)
    
    # 刪除數據
        # 基於queryset
    models.User.objects.filter(name='qzk').delete()
    # 基於對象的方法
    user_obj=models.User.objects.filter(name='qzk').first()
    user_obj.delete()
    
    # filter() 內能夠放多個限制條件的關鍵參數,可是須要注意的是多個條件之間是and關係
    # get()
    # exclude(**kwargs): 它包含了與說給篩選條件不匹配的對象
    # order_by(*field): 對查詢結果排序 默認是升序, 能夠在排序的字段名前面加'-'號,就是降序排列
    # reverse(): 對查詢結果反向排序》》》》》前面要現有排序才能反向
    # count():返回數據庫中匹配查詢(Queryset)的對象數量
    # first(): 返回第一條記錄
    res=models.User.objects.all()[0]  # 不支持負數索引
    
    
    # distinct(): 返回結果中剔除重複的記錄,去重的對象必須是徹底相同的
    
   """只要是queryset對象 就能夠無限制的點 queryset方法"""



"""神奇的雙下劃線查詢"""
# 查詢年齡大於44的用戶
res= models.User.objects.filter(age__gt=44)
# 查詢年齡小於44的用戶
res= models.User.objects.filter(age__lt=44)
# 查詢年齡大於等於44的用戶
res= models.User.objects.filter(age__gte=44)
# 查詢年齡小於等於44的用戶
res= models.User.objects.filter(age__lte=44)


# 查詢名字中包含n的用戶
res=models.User.objects.filter(name__contains='n')  # 在mysql中區分大小寫
res=models.User.objects.filter(name__icontains='n')  # 忽略大小寫

# 查詢名字以j開頭的
res=models.User.objects.filter(name__startwith='j')
# 查詢名字以n結尾的
res=models.User.objects.filter(name__endwith='j')

單表查詢示例二

class Book(models.Model):
  	name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_place=2)
    publish = models.CharField(max_length=32)
    author = models.CharField(max_length=32)
    create_time = models.DateField(null=True)
    # 配置auto_now_add=True,建立數據記錄的時候會把當前時間添加到數據庫。
    # 配置上auto_now=True,每次更新數據記錄的時候會更新該字段。
新增數據
# 第一種:有返回值,而且就是當前被建立的數據對象
    modles.Book.objects.create(name='',price='',publish='',author='',create_time='2019-5-1')
    # 第二種:先實例化產生對象,而後調用save方法保存
    book_obj = models.Book(name='',price='',publish='',author='',create_time='2019-5-1')
    book_obj.save()
    # 2.驗證時間格式字段便可以傳字符串也能夠傳時間對象
    import datetime
    ctime = datetime.datetime.now()
    book = models.Book.objects.create(name='',price='',author='',create_time=ctime)
刪除數據
"""刪除數據"""
    # 1.刪除書名爲xxx的這本書  queryset方法
    res = models.Book.objects.filter(name='').delete()
    print(res)
    # 2.刪除書名爲xxx的這本書  queryset方法
    res = models.Book.objects.filter(name='').first()
    res.delete()
修改數據
# 1.queryset修改
    models.Book.objects.filter(name='').update(price='')
    # 2.對象修改
    book = models.Book.objects.filter(name='').first()
    book.price = 66.66
    book.save()  # 對象只有保存方法 這樣也能實現修改需求
查詢數據
<1> all():                 # 查詢全部結果
    <2> filter(**kwargs):      # 它包含了與所給篩選條件相匹配的對象
    <3> get(**kwargs):         # 返回與所給篩選條件相匹配的對象,返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。(源碼就去摟一眼~詮釋爲什麼只能是一個對象)
    <4> exclude(**kwargs):     # 它包含了與所給篩選條件不匹配的對象
    <5> order_by(*field):      # 對查詢結果排序('-id')/('price')
    
    <6> reverse():             #  對查詢結果反向排序 	>>>前面要先有排序才能反向
    <7> count():               # 返回數據庫中匹配查詢(QuerySet)的對象數量。
    <8> first():               # 返回第一條記錄
    <9> last():                # 返回最後一條記錄
    <10> exists():             # 若是QuerySet包含數據,就返回True,不然返回False
    <11> values(*field):       # 返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系model的實例化對象,而是一個可迭代的字典序列
    <12> values_list(*field):  # 它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列
    <13> distinct():           # 從返回結果中剔除重複紀錄 
   							# 必須徹底同樣才能夠去重(意味着帶了id就沒有意義了)
   res = models.Book.objects.all().values('name').distinct()  # 先查一個重複的值再去重
# 查詢名字中包含字母n的用戶  sqlite數據庫演示不出來大小寫的狀況!!!
    res = models.Author.objects.filter(name__contains='n')
    res = models.Author.objects.filter(name__icontains='n')
    print(res)
    res = models.User.objects.filter(name__icontains='e')  # 無視大小寫
    print(res)

    # 查詢名字以j開頭的用戶
    res = models.User.objects.filter(name__startswith='j')
    print(res)
    # 查詢名字以n結尾的用戶
    res = models.User.objects.filter(name__endswith='n')
    print(res)

    # 查詢註冊是在2017年的用戶
    res = models.User.objects.filter(register_time__year=2017)  # sqlite對日期格式不太精準
    print(res)
基於雙下劃線的查詢
# 價格 大於 小於 大於等於 小於等於
filter(price__gt='90')  # 大於
filter(price__lt='90')  # 小於
filter(price_gte='90')  # 大於等於
filter(price_lte='90')  # 小於等於

# 存在與某幾個條件中
filter(price__in=['11','22','33'])  # 價格在什麼列表中的價格中
# 在某個範圍內
filter(price__range=[50,90])  

# 模糊查詢
filter(title__contains='西')  # 標題中包含西字
filter(title__icontains='P')  # 不區分大小寫的 包含P的標題

# 以什麼開頭 以什麼結尾

# 按年查詢
filter(create_time__year='2017')

多表查詢

建立圖書管理系統表(給做者表加一張做者詳情表爲了一對一的查詢),詮釋一對一關聯其實就是外健關聯再加一個惟一性約束而已mysql

ForeignKey(unique=Ture)		>>>		OneToOneField()		
# 即一對一能夠用ForeignKey來作,可是須要設惟一性約束而且會報警告信息,不建議使用,建議用OneToOneField
# 用了OneToOneField和用ForeignKey會自動在字段後面加_id
# 用了ManyToMany會自動建立第三張表

1.一對多的書籍記錄增刪改查

# 針對外鍵關聯的字段 兩種添加方式
# 第一種經過publish_id
# 第二種經過publish傳出版社對象

# 刪除書籍直接查詢刪除便可,刪除出版社會級聯刪除

# 編輯數據也是兩種對應的方式(對象點的方式(這裏能點publish和publish_id)最後點save(),queryset方式update())

2.多對多的書籍與做者的增刪改查

"""前提:先獲取書籍對象,再經過書籍對象點authors來進行書籍做者的增刪改查"""
# 1.給書籍新增做者add
  # 1.add能夠傳做者id,也能夠直接傳做者對象,而且支持傳多個位置參數(不要混着用)
  
# 2.給書籍刪除做者remove
	# 1.remove一樣能夠傳id,對象,而且支持傳多個位置參數(不要混着用)

# 3.直接清空書籍對象全部的做者數據clear()不用傳任何參數

# 4.修改書籍對象所關聯的做者信息set,注意點set括號內必須傳可迭代對象,裏面能夠傳id,對象
	
"""總結:一對多增刪改,多對多add,remove,clear,set"""
# 新增
    # 直接寫id
    	models.Book.objects.create(title='紅樓夢',price=66.66,publish_id=1)
    # 傳數據對象
    	publish_obj = models.Publish.objects.filter(pk=2).first()
    	models.Book.objects.create(title='三國演義',price=199.99,publish=publish_obj)

 # 修改
    # queryset修改
    	models.Book.objects.filter(pk=1).update(publish_id=3)
    	publish_obj = models.Publish.objects.filter(pk=2).first()
    	models.Book.objects.filter(pk=1).update(publish=publish_obj)
    # 對象修改
    	book_obj = models.Book.objects.filter(pk=1).first()
    	book_obj.publish_id = 3  # 點表中真實存在的字段名
    	book_obj.save()
    	publish_obj = models.Publish.objects.filter(pk=2).first()
    	book_obj.publish = publish_obj  # 點orm中字段名 傳該字段對應的表的數據對象
    	book_obj.save()

# 刪除
	# queryset刪除
    	models.Book.objects.filter(pk=1).delete()
    	models.Publish.objects.filter(pk=1).delete()
	# 對象刪除
    	book_obj = models.Book.objects.filter(pk=3).first()
    	book_obj.delete()


# 給書籍綁定與做者之間的關係
    # 添加關係 add:add支持傳數字或對象,而且均可以傳多個
    	book_obj = models.Book.objects.filter(pk=3).first()
    	book_obj.authors.add(1)
    	book_obj.authors.add(2,3)
    	author_obj = models.Author.objects.filter(pk=1).first()
    	author_obj1 = models.Author.objects.filter(pk=3).first()
    	book_obj.authors.add(author_obj)
    	book_obj.authors.add(author_obj,author_obj1)
# 修改書籍與做者的關係  set()  set傳的必須是可迭代對象!!!
    	book_obj = models.Book.objects.filter(pk=3).first()
    # 能夠傳數字和對象,而且支持傳多個
    	book_obj.authors.set((1,))
    	book_obj.authors.set((1,2,3))
    	author_list = models.Author.objects.all()
    	book_obj = models.Book.objects.filter(pk=3).first()
    	book_obj.authors.set(author_list)

# 刪除書籍與做者的綁定關係
	# 方法1:
    	book_obj = models.Book.objects.filter(pk=3).first()
    	book_obj.authors.remove(1)
    	book_obj.authors.remove(2,3)
    # 方法2:
    	author_obj = models.Author.objects.all().first()
    	author_list = models.Author.objects.all()
    	book_obj.authors.remove(author_obj)
    	book_obj.authors.remove(*author_list)  # 須要將queryset打散


    # 清空  clear()  清空的是你當前這個表記錄對應的綁定關係
    # book_obj = models.Book.objects.filter(pk=3).first()
    # book_obj.authors.clear()

正向反向概念

# 正向與方向的概念解釋

# 一對一
# 正向:author---關聯字段在author表裏--->authordetail		按字段
# 反向:authordetail---關聯字段在author表裏--->author		按表名小寫
	# 查詢jason做者的手機號   正向查詢
	# 查詢地址是 :山東 的做者名字   反向查詢
  
# 一對多
# 正向:book---關聯字段在book表裏--->publish		按字段
# 反向:publish---關聯字段在book表裏--->book		按表名小寫_set.all() 由於一個出版社對應着多個圖書

# 多對多
# 正向:book---關聯字段在book表裏--->author		按字段
# 反向:author---關聯字段在book表裏--->book		按表名小寫_set.all() 由於一個做者對應着多個圖書
  
  

# 連續跨表
	# 查詢圖書是三國演義的做者的手機號,先查書,再正向查到做者,在正向查手機號

# 總結:基於對象的查詢都是子查詢,這裏能夠用django配置文件自動打印sql語句的配置作演示

基於對象的表查詢

# 正向
    # 查詢書籍是三國演義的出版社郵箱
    	book_obj = models.Book.objects.filter(title='三國演義').first()
    	print(book_obj.publish.email)
    # 查詢書籍是金梅的做者的姓名
    	book_obj = models.Book.objects.filter(title='金梅').first()
    	print(book_obj.authors)  # app01.Author.None
    	print(book_obj.authors.all())
    # 查詢做者爲jason電話號碼
    	user_obj = models.Author.objects.filter(name='jason').first()
    	print(user_obj.authordetail.phone)
# 反向
    # 查詢出版社是東方出版社出版的書籍                  一對多字段的反向查詢
    	publish_obj = models.Publish.objects.filter(name='東方出版社').first()
    	print(publish_obj.book_set)  # app01.Book.None
    	print(publish_obj.book_set.all())

    # 查詢做者jason寫過的全部的書                      多對多字段的反向查詢
    	author_obj = models.Author.objects.filter(name='jason').first()
    	print(author_obj.book_set)  # app01.Book.None
    	print(author_obj.book_set.all())

    # 查詢做者電話號碼是110的做者姓名                   一對一字段的反向查詢
    	authordetail_obj = models.AuthorDetail.objects.filter(phone=110).first()
    	print(authordetail_obj.author.name)

基於雙下劃線的查詢

# 一對一
-連表查詢
		-一對一雙下劃線查詢
			-正向:按字段,跨表能夠在filter,也能夠在values中
			-反向:按表名小寫,跨表能夠在filter,也能夠在values中
    # 查詢jason做者的手機號   正向查詢  跨表的話,按字段
    # ret=Author.objects.filter(name='jason').values('authordetail__phone')
    # 以authordetail做爲基表 反向查詢,按表名小寫  跨表的話,用表名小寫
    # ret=AuthorDetail.objects.filter(author__name='jason').values('phone')
    
    # 查詢jason這個做者的性別和手機號
    # 正向
    # ret=Author.objects.filter(name='jason').values('sex','authordetail__phone')

    # 查詢手機號是13888888的做者性別
    # ret=Author.objects.filter(authordetail__phone='13888888').values('sex')
    # ret=AuthorDetail.objects.filter(phone='13888888').values('author__sex')
    
"""
總結 其實你在查詢的時候先把orm查詢語句寫出來,再看用到的條件是否在當前表內,在就直接獲取,不在就按照正向按字段反向按表名來查便可
好比:
	1.查詢出版社爲北方出版社的全部圖書的名字和價格
	res1 = Publish.objects.filter(name='').values('book__name','book__price')
	res2 = Book.objects.filter(publish__name='').values('name','price')
	2.查詢北方出版社出版的價格大於19的書
	res1 = Publish.objects.filter(name='',book__price__gt=19).values('book__name','book__price)
"""

基於雙下滑線的查詢示例

# 正向
    # 查詢書籍爲三國演義的出版社地址
    	res = models.Book.objects.filter(title='三國演義').values('publish__addr','title')
    	print(res)
    # 查詢書籍爲金梅的做者的姓名
    	res = models.Book.objects.filter(title='金梅').values("authors__name",'title')
    	print(res)
    # 查詢做者爲jason的家鄉
    	res = models.Author.objects.filter(name='jason').values('authordetail__addr')
    	print(res)
# 反向
    # 查詢南方出版社出版的書名
    	res = models.Publish.objects.filter(name='南方出版社').values('book__title')
    	print(res)
    # 查詢電話號碼爲120的做者姓名
    	res = models.AuthorDetail.objects.filter(phone=120).values('author__name')
    	print(res)
    # 查詢做者爲jason的寫的書的名字
    	res = models.Author.objects.filter(name='jason').values('book__title')
    	print(res)
    # 查詢書籍爲三國演義的做者的電話號碼
    	res = models.Book.objects.filter(title='三國演義').values('authors__authordetail__phone')
    	print(res)

    # 查詢jason做者的手機號
    # 正向
    	res = models.Author.objects.filter(name='jason').values('authordetail__phone')
    	print(res)
    # 反向
    	res = models.AuthorDetail.objects.filter(author__name='jason').values('phone')
    	print(res)

    # 查詢出版社爲東方出版社的全部圖書的名字和價格
    # 正向
    	res = models.Publish.objects.filter(name='東方出版社').values('book__title','book__price')
    	print(res)
    # 反向
    	res = models.Book.objects.filter(publish__name='東方出版社').values('title','price')
    	print(res)

    # 查詢東方出版社出版的價格大於400的書
    # 正向
    	res = models.Publish.objects.filter(name="東方出版社",book__price__gt=400).values('book__title','book__price')
    	print(res)
    # 反向
    	res = models.Book.objects.filter(price__gt=400,publish__name='東方出版社').values('title','price')
    	print(res)

聚合查詢

# 聚合查詢  aggregate
    from django.db.models import Max,Min,Count,Sum,Avg
    # 查詢全部書籍的做者個數
    res = models.Book.objects.filter(pk=3).aggregate(count_num=Count('authors'))
    print(res)
    # 查詢全部出版社出版的書的平均價格
    res = models.Publish.objects.aggregate(avg_price=Avg('book__price'))
    print(res)  # 4498.636
    # 統計東方出版社出版的書籍的個數
    res = models.Publish.objects.filter(name='東方出版社').aggregate(count_num=Count('book__id'))
    print(res)

分組查詢

# 分組查詢(group_by)   annotate
    # 統計每一個出版社出版的書的平均價格
    res =models.Publish.objects.annotate(avg_price=Avg('book__price')).values('name','avg_price')
    print(res)
    # 統計每一本書的做者個數
    res = models.Book.objects.annotate(count_num=Count('authors')).values('title','count_num')
    print(res)
    # 統計出每一個出版社賣的最便宜的書的價格
    res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price')
    print(res)
    # 查詢每一個做者出的書的總價格
    res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price')
    print(res)
相關文章
相關標籤/搜索