雙下查詢,ORM建立外來鍵,多表查詢
阿新 • • 發佈:2022-05-17
雙下劃線查詢方法
比較運算
# 關鍵字: 大於: __gt 小於: __lt 大於等於: __gte 小於等於: __lte # 舉例: res = models.User.objects.filter(age__gt=18) print(res) # 年齡大於18 res1 = models.User.objects.filter(age__lt=18) print(res) # 年齡小於18 res2 = models.User.objects.filter(age__gte=18) print(res2) # 年齡大於等於18 res3 = models.User.objects.filter(age__lte=18) print(res3) # 年齡小於等於18
在某一資料集內:
# 關鍵字:__in=['資料集']
# 舉例:
res = models.User.objects.filter(age__in=[10,20,30,40])
print(res)
在某一範圍內:
# 關鍵字:__range=[]
# 舉例:
res = models.User.objects.filter(age__range=[19,40]) # 包含19和40
print(res)
模糊查詢:
# 關鍵字:__contain='' 區分大小寫 __icontain='' 不區分大小寫 # 舉例: 查詢姓名中包含字母k的使用者 res = models.User.objects.filter(name__contains='k') print(res) res1 = models.User.objects.filter(name__icontains='k') print(res1)
以什麼開頭/結尾:
# 關鍵字:__startwith='' 以什麼開頭
__endswith='' 以什麼結尾
__istartwith='' 不區分大小寫
__iendswith='' 不區分大小寫
# 舉例:
models.User.objects.filter(name_ _startswith="n" )
models.User.objects.filter(name_ _endswith="n" )
按照日期查詢:
# 關鍵字: __month='1' # 按照月份取 __year='2020' # 按照年份 __day='29' # 按照天篩選 # 舉例: res = models.User.objects.filter(register_time__month='01') print(res) res1= models.User.objects.filter(register_time__day='02') print(res1) res3 = models.User.objects.filter(register_time__year='2022') print(res3) res4 = models.User.objects.filter(register_time__year='2022',register_time__month='02') print(res4)
ORM建立外來鍵
以書籍,出版社,作者,作者資訊這4張表為例
書籍和出版社的關係:
一本書籍只能由一個出版社出版,一個出版社可以出版多本書。
關係為:一對多(ForeignKey),書籍是多所以外來鍵建立在書籍表中。
書籍和作者的關係:
一本書可以由多個作者創作,一個作者同樣也可以創作多本書。
關係為:多對多(ManyToManyField),需要建立第三張表來表示關係
作者和作者資訊的關係:
一條資訊對應一個作者,一個作者對應一條資訊。
關係為:一對一(OneToOneField),外來鍵應建立在查詢頻率較高的表中。
一對多外來鍵關係
"""在orm中 外來鍵欄位建在多的一方"""
多對多外來鍵關係
"""在orm中 可以直接寫在查詢頻率較高的表中(自動建立第三張表)"""
一對一外來鍵關係
"""在orm中 直接寫在查詢頻率較高的表中"""
"""
ManyToManyField不會在表中建立實際的欄位 而是告訴django orm自動建立第三張關係表
ForeignKey、OneToOneField會在欄位的後面自動新增_id字尾 如果你在定義模型類的時候自己新增
了該字尾那麼遷移的時候還會再次新增_id_id 所以不要自己加_id字尾
ps:三個關鍵字裡面的引數
to用於指定跟哪張表有關係 自動關聯主鍵
to_field\to_fields 也可以自己指定關聯欄位
"""
#書籍
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8,decimal_places=2)
# 一對多
publish = models.ForeignKey(to='Publish')
# 多對多
authors = models.ManyToManyField(to='Author') # 自動建立書籍和作者的第三張關係表
#出版
class Publish(models.Model):
title = models.CharField(max_length=32)
#作者
class Author(models.Model):
name = models.CharField(max_length=32)
# 一對一
author_detail = models.OneToOneField(to='AuthorDetail')
#作者資訊
class AuthorDetail(models.Model):
addr = models.CharField(max_length=32)
phone = models.BigIntegerField()
ORM外來鍵欄位操作
一對一,一對多(OneToOneField,ForeignKey)
新增外來鍵欄位值:
#第一種方法
models.Book.objects.create(title='JAVA',price=123456,publish_id=1) # 直接填寫關聯資料的主鍵值
#第二種方法
publish_obj = models.Publish.objects.filter(pk=2).first() # 獲取外來鍵物件
models.Book.objects.create(title='JS',price=11111,publish=publish_obj)
修改外來鍵欄位值:
#第一種方法
models.Book.objects.filter(pk=1).update(publish_id=2) # 直接修改publish_id的值
#第二種方法
publish_obj = models.Publish.objects.filter(pk=2).first() # 先獲取物件,這裡是修改出版社那麼要先獲取對應出版社物件
models.Book.objects.filter(pk=1).update(publish=publish_obj) # 修改publish
多對多(ManyToManyField)
# 新增關係
#第一種方法
book_obj = models.Book.objects.filter(pk=2).first() # 先獲取對應書籍物件
book_obj.authors.add(1) # 然後給書籍物件的authors欄位傳入作者的id # 在第三張關係表中新增資料
book_obj.authors.add(1, 3) #可以直接填寫資料主鍵值
#第二種方法
author_obj1 = models.Author.objects.filter(pk=3).first() # 先獲取作者物件
author_obj2 = models.Author.objects.filter(pk=4).first()
book_obj.authors.add(author_obj1)
book_obj.authors.add(author_obj1,author_obj2) # 會在第三張表中新增2條資料(2,3)(2,4)
#修改關係
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.set([3, ])
book_obj.authors.set([1, 2])
author_obj1 = models.Author.objects.filter(pk=3).first()
author_obj2 = models.Author.objects.filter(pk=4).first()
book_obj.authors.set([author_obj1, ])
book_obj.authors.set([author_obj1, author_obj2])
#移除關係
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.remove(3)
book_obj.authors.remove(3,4)
author_obj1 = models.Author.objects.filter(pk=1).first()
author_obj2 = models.Author.objects.filter(pk=2).first()
book_obj.authors.remove(author_obj1)
book_obj.authors.remove(author_obj1,author_obj2)
#清空關係
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.clear()
1.第三張關係表建立資料
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.add()
括號內可以放主鍵值也可以放資料物件 並且都支援多個
2.第三張關係表修改資料
book_obj.authors.set()
括號內必須是一個可迭代物件 元素同樣支援主鍵值或者資料物件
3.第三張關係表刪除資料
book_obj.authors.remove()
括號內可以放主鍵值也可以放資料物件 並且都支援多個
4.第三張關係表清空指定資料
book_obj.authors.clear()
括號內無需傳值 直接清空當前表在第三張關係表中的繫結記錄
正向查詢和反向查詢
如果一張表有外來鍵欄位,並且是從這張表開始查詢的,那麼就叫作正向查詢。
相反的,如果從關聯表開始查詢的,就叫反向查詢。
由書籍查詢出版社 外來鍵欄位在書籍表中 那麼書查出版社就是'正向'
由出版社查詢書籍 外來鍵欄位不在出版社表 那麼出版社查書就是'反向'
"""
查詢口訣
正向查詢按外來鍵欄位名
反向查詢按表名小寫
"""
多表查詢
表資訊
#書籍
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8,decimal_places=2)
# 一對多
publish = models.ForeignKey(to='Publish')
# 多對多
authors = models.ManyToManyField(to='Author') # 自動建立書籍和作者的第三張關係表
#出版
class Publish(models.Model):
title = models.CharField(max_length=32)
#作者
class Author(models.Model):
name = models.CharField(max_length=32)
# 一對一
author_detail = models.OneToOneField(to='AuthorDetail')
#作者資訊
class AuthorDetail(models.Model):
addr = models.CharField(max_length=32)
phone = models.BigIntegerField()
基於物件的跨表查詢(子查詢)
正向查詢
1.查詢Python程式設計書籍對應的出版社
(1)先獲取書籍物件
book_obj = models.Book.objects.filter(title='Python程式設計').first()
(2)進行跨表查詢,從書籍找到出版社是正向查詢,使用外來鍵欄位名
res = book_obj.publish # 返回的是對應的出版社物件
print(res.title) # 上海出版社
2.查詢python程式設計書籍創作的作者
# 首先先獲取書籍物件
book_obj = models.Book.objects.filter(title='Python程式設計').first()
# 進行跨表查詢,從書籍找到出版社是正向查詢,使用外來鍵欄位名
# res = book_obj.authors
# print(res) # app01.Author.None # 此時返回none,如果返回有多個還需要加all()
res = book_obj.authors.all() # 返回多個物件
print(res) # <QuerySet [<Author: Author object>, <Author: Author object>]>
反向查詢
3.查詢上海出版社出版的書籍
#首先獲取出版社物件
publish_obj = models.Publish.objects.filter(title='上海出版社').first()
#進行跨表查詢,從出版社找到書籍是反向查詢(外來鍵不在出版社表中),使用表名小寫
# res = publish_obj.book_set # 反向查詢時表名小寫還需要加上 _set
# print(res) # app01.Book.None
#由於一個出版社可以出版多本書籍,返回結果可能是多個,還需要加上 all()
res = publish_obj.book_set.all() #返回多個書籍物件
print(res) # <QuerySet [<Book: Book object>, <Book: Book object>]>
4.查詢電話為1的作者(在一對一關係中的反向查詢表名小寫後不要跟 _set)
author_detail_obj = models.AuthorDetail.objects.filter(phone=1).first()
res = author_detail_obj.author # 返回作者物件
print(res.name) # 張三
基於雙下劃線的跨表查詢(多表連線查詢)
1.查詢Python程式設計書籍對應的出版社名稱
res = models.Book.objects.filter(title='Python程式設計').values('publish__title')
print(res) # <QuerySet [{'publish__title': '上海出版社'}]>
2.查詢作者張三的手機號和地址
res = models.Author.objects.filter(name='張三').values('author_detail__phone','author_detail__addr')
print(res) # <QuerySet [{'author_detail__phone': 1, 'author_detail__addr': '上海'}]>
雙下劃線查詢擴充套件
1.查詢Python程式設計書籍對應的出版社名稱
方法一:
res = models.Publish.objects.filter(book__title='Python程式設計') # 返回出版社物件<QuerySet [<Publish: Publish object>]>
print(res[0].title) # 上海出版社
方法二:
res = models.Publish.objects.filter(book__title='Python程式設計').values('title')
print(res) # <QuerySet [{'title': '上海出版社'}]>
print(res[0].get('title')) # 上海出版社
方法三:
res = models.Publish.objects.filter(book__title='Python程式設計').first()
print(res.title) # 上海出版社
2.查詢作者王五的手機號和地址
res = models.AuthorDetail.objects.filter(author__name='王五').values('phone','addr')
print(res) # <QuerySet [{'phone': 3, 'addr': '北京'}]>
print(res[0].get('phone')) # 3
print(res[0].get('addr')) # 北京
'''連續跨表操作'''
1.查詢python程式設計書籍對應的作者的手機號
res = models.Book.objects.filter(title='PYthon程式設計').values('authors__author_detail__phone')
print(res) # <QuerySet [{'authors__author_detail__phone': 1}, {'authors__author_detail__phone': 2}]>
如何檢視SQL語句
方式1:如果結果集物件是queryset 那麼可以直接點query檢視
方式2:配置檔案固定配置
適用面更廣 只要執行了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',
},
}
}