單表操作
# django自帶的sqlite3數據庫對日期格式不是很敏感,處理的時候容易出錯 # 將自帶的數據庫換爲mysql,之前有介紹 # 在model.py加入表結構 class User(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() register_time = models.DateField() ''' DateField DateTimeField 兩個重要參數 auto_now:每次操作數據的時候,該字段會自動將當前時間更新 auto_now_add:在創建數據的時候會自動將當前創建時間記錄下來,之後只要不修改,那麼就一直不變 ''' def __str__(self): return '對象輸出:%s' % self.name
測試腳本
當你只是想測試django中的某一個py文件內容,那麼你可以不用書寫前後端交互的形式,而是直接寫一個測試腳本即可
腳本代碼無論是寫在應用下的tests.py還是自己單獨開設py文件都可以
''' 測試環境的準備 去manage.py中拷貝前四行代碼 然後自己寫兩行 ''' import os import sys if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day64.settings") import django django.setup() # 在這個代碼塊的下面就可以測試django裏面的單個py文件了
單表的增刪改查
-
數據的增
# 單表操作 增刪改查 # 數據的增加 # 方式一:直接對應標識增加 res = models.User.objects.create(name='xiaozhang',age=35,register_time='2020-01-11') print(res) # 方式二: 將對象方式增加 import datetime now_time = datetime.datetime.now() # 獲取當前日期 res_obj = models.User(name='xiaoli',age=25,register_time=now_time) res_obj.save()
-
數據的刪除
# 數據的刪除 # 方式一 res = models.User.objects.filter(pk=2).delete() # 刪除主鍵值是2的數據 print(res) # (1, {'app01.User': 1}) ''' pk會自動查找到當前表的主鍵字段,指代的就是當前表的主鍵字段 用pk之後,就不需要知道當前表的主鍵字段是什麼(例如:uid,pid,sid...) ''' # 方式二 use_obj = models.User.objects.filter(pk=1).first() use_obj.delete()
-
數據的修改
# 數據的修改 res = models.User.objects.filter(pk=3).update(name='xiaohuang') print(res) # 1 # 查找數據的方式還有get方法,該方法返回的直接就是當前數據對象,該方法不推薦使用,因爲一旦獲取的數據不存在,該方法會直接報錯 # 查找數據的方式filter,一般還是用filter方式 user_obj = models.User.objects.filter(pk=2) user_obj1 = models.User.objects.get(pk=2) print(user_obj) # <QuerySet []> 返回是空,但是不不報錯 print(user_obj1) # 查找的主鍵值數據不存在,報錯 user_obj.name = 'egonPPP' user_obj.save()
必知必會13條
-
all() 查詢所有數據
res = models.User.objects.all() print(res) # <QuerySet [<User: 對象輸出:xiaohuang>, <User: 對象輸出:xiaozhang>, <User: 對象輸出:xiaoli>]>
-
filter() 帶有過濾條件的查詢
res = models.User.objects.filter(name='xiaoli') print(res) # <QuerySet [<User: 對象輸出:xiaoli>]>
-
get() 直接拿數據對象 但是條件不存在直接報錯
res = models.User.objects.get(pk=1) print(res) # 報錯 app01.models.DoesNotExist: User matching query does not exist.
-
first() 拿queryset裏面第一個元素
res = models.User.objects.filter(name='xiaoli').first() print(res) # 對象輸出:xiaoli
-
last() 拿queryset裏面最後一個元素
res = models.User.objects.filter(name='xiaohuang').last() print(res) # 對象輸出:xiaohuang res = models.User.objects.all().last() print(res) # 對象輸出:xiaoli
-
values() 可以指定獲取的數據字段 select name,age from ... 類似列表套字典
res = models.User.objects.values('name','age') print(res) # <QuerySet [{'name': 'xiaohuang', 'age': 20}, {'name': 'xiaozhang', 'age': 35}, {'name': 'xiaoli', 'age': 25}]>
-
values_list() 也是指定獲取數據字段 類似列表套元祖
res = models.User.objects.values_list('name','age') print(res) # <QuerySet [('xiaohuang', 20), ('xiaozhang', 35), ('xiaoli', 25)]>
-
distinct() 去重
res = models.User.objects.values('name','age').distinct() print(res) # <QuerySet [{'name': 'xiaohuang', 'age': 20}, {'name': 'xiaozhang', 'age': 35}, {'name': 'xiaoli', 'age': 25}]> ''' 去重一定要是一模一樣的數據纔可以,如果帶有主鍵那麼肯定是不一樣的,必須是不帶主鍵字段纔可以 '''
-
order_by() 排序 默認是升序
res = models.User.objects.order_by('age') # 默認升序 print(res) # <QuerySet [<User: 對象輸出:xiaohuang>, <User: 對象輸出:xiaohuang>, <User: 對象輸出:xiaoli>, <User: 對象輸出:xiaozhang>]> res = models.User.objects.order_by('-age') # 降序加一個減號 print(res) # <QuerySet [<User: 對象輸出:xiaozhang>, <User: 對象輸出:xiaoli>, <User: 對象輸出:xiaohuang>, <User: 對象輸出:xiaohuang>]>
-
reverse() 反轉的前提是 數據已經排過序了 order_by()
res = models.User.objects.order_by('age').reverse() print(res) # <QuerySet [<User: 對象輸出:xiaozhang>, <User: 對象輸出:xiaoli>, <User: 對象輸出:xiaohuang>, <User: 對象輸出:xiaohuang>]>
-
count() 統計當前數據的個數
res = models.User.objects.count() print(res) # 4
-
exclude() 排除在外
res = models.User.objects.exclude(name='xiaohuang') print(res) # <QuerySet [<User: 對象輸出:xiaozhang>, <User: 對象輸出:xiaoli>]>
-
exists() 基本用不到因爲數據本身就自帶布爾值 返回的是布爾值
res = models.User.objects.filter(name='xiaoli').exists() print(res) # True
內部查詢封裝sql語句(補充)
查詢內部封裝的sql語句
查詢sql語句的方式,只能用於queryset對象,只有queryset對象才能夠點擊query查看內部的sql語句
# 方式一 query 只有是queryset對象才能夠點擊query查看內部的sql語句 res = models.User.objects.values_list('name', 'age').query print(res) # SELECT `app01_user`.`name`, `app01_user`.`age` FROM `app01_user` # 方式二 # 所有sql語句都能查詢,修改settings配置文件 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level': 'DEBUG', }, } }
神奇的雙下劃線查詢
# 查詢年齡大於20歲的數據 res = models.User.objects.filter(age__gt=20) print(res) # <QuerySet [<User: 對象輸出:xiaozhang>, <User: 對象輸出:xiaoli>]> # 年齡小於20歲的數據 res = models.User.objects.filter(age__lt=20) print(res) # <QuerySet []> # 大於等於 小於等於 res = models.User.objects.filter(age__gte=20) # 大於等於 print(res) # <QuerySet [<User: 對象輸出:xiaohuang>, <User: 對象輸出:xiaozhang>, <User: 對象輸出:xiaoli>, <User: 對象輸出:xiaohuang>]> res1 = models.User.objects.filter(age__lte=20) # 小於等於 print(res1) # <QuerySet [<User: 對象輸出:xiaohuang>, <User: 對象輸出:xiaohuang>]> # 查詢年齡是25或者35 res = models.User.objects.filter(age__in=[25,35]) print(res) # <QuerySet [<User: 對象輸出:xiaozhang>, <User: 對象輸出:xiaoli>]> # 查詢年齡在25到35歲之間的 首尾都要 res = models.User.objects.filter(age__range=[25,35]) print(res) # <QuerySet [<User: 對象輸出:xiaozhang>, <User: 對象輸出:xiaoli>]> # 查詢出名字裏面含有h的數據 模糊查詢 區分大小寫 res = models.User.objects.filter(name__contains='h') print(res) # <QuerySet [<User: 對象輸出:xiaohuang>, <User: 對象輸出:xiaozhang>, <User: 對象輸出:xiaohuang>]> # 查詢出名字裏面含有l的數據 模糊查詢 忽略大小寫 res = models.User.objects.filter(name__icontains='l') print(res) # <QuerySet [<User: 對象輸出:xiaoli>, <User: 對象輸出:xiaoLii>]> # # 查詢首字母是x開頭的數據 res = models.User.objects.filter(name__startswith='x') print(res) # # 查詢最後是以x結尾的數據 res = models.User.objects.filter(name__endswith='x') print(res) # 查詢註冊時間是2020年1月的數據 res = models.User.objects.filter(register_time__year='2020',register_time__month='01') print(res) # <QuerySet [<User: 對象輸出:xiaozhang>, <User: 對象輸出:xiaohuang>]> ''' SELECT `app01_user`.`id`, `app01_user`.`name`, `app01_user`.`age`, `app01_user`.`register_time` FROM `app01_user` WHERE (`app01_user`.`register_time` BETWEEN '2020-01-01' AND '2020-12-31' AND EXTRACT(MONTH FROM `app01_user`.`register_time`) = 1) LIMIT 21; args=('2020-01-01', '2020-12-31', 1) '''
多表操作
多表操作我們以圖書管理系統爲例:
書對出版社:一對多
書對作者:多對多
作者對作者詳情:一對一
# 在model.py中建立ORM表結構 # 圖書表 class Book(models.Model): title = models.CharField(max_length=64) price = models.DecimalField(max_digits=8,decimal_places=2) publish_date = models.DateField(auto_now_add=True) # 一對多 publish = models.ForeignKey(to='Publish') # 多對的 authors = models.ManyToManyField(to='Authors') # 出版社表 class Publish(models.Model): name = models.CharField(max_length=32) addr = models.CharField(max_length=64) email = models.EmailField() # 該字段類型不是給modles看的,而是給後面校驗性組件看的 # 作者表 class Authors(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() # 一對一 author_detail = models.OneToOneField(to='AuthorDetail') # 作者詳情表 class AuthorDetail(models.Model): phone = models.BigIntegerField() # 電話號碼用BigIntegerField或者CharField addr = models.CharField(max_length=64)
一對多外鍵增刪改查
-
數據的增加
# 增加 給書籍綁定出版社 res = models.Book.objects.create(title='三國演義',price=123.33,publish_id=1) res = models.Book.objects.create(title='論語',price=110.59,publish_id=2) res = models.Book.objects.create(title='紅樓夢',price=83.15,publish_id=1) res = models.Book.objects.create(title='聊齋',price=99.35,publish_id=2) # 虛擬字段 對象 給書籍綁定出版社 publish_obj = models.Publish.objects.filter(pk=2).first() print(publish_obj.name) models.Book.objects.create(title='聊齋', price=123.33, publish=publish_obj)
-
數據的刪除
# 刪除 res = models.Book.objects.filter(pk=5).delete() # 級聯刪除 print(res) # (3, {'app01.Book_authors': 2, 'app01.Book': 1})
-
數據的修改
# 修改 修改出版社 models.Book.objects.filter(pk=2).update(publish_id=2) # 虛擬字段修改 對象 修改出版社信息 publish_obj = models.Publish.objects.filter(pk=1).first() models.Book.objects.filter(pk=2).update(publish=publish_obj)
多對多外鍵增刪改查
-
數據的增加
# 增加 給書籍添加作者 add # 方式一 book_obj = models.Book.objects.filter(pk=2).first() print(book_obj.title) # 三國演義 print(book_obj.authors) # app01.Authors.None 就類似於已經到了第三張關係表 book_obj.authors.add(1) # 給書籍id爲2的書籍綁定一個主鍵爲1的作者 如果已經存在,則不變 book_obj.authors.add(2, 3) # 給書籍id爲2的書籍綁定一個主鍵爲2和3的作者 # 方式二 # 1、獲取書籍id爲2的書籍 book_obj = models.Book.objects.filter(pk=2).first() # 2、獲取到作者表中的主鍵值爲1/2/3的數據對象 author_obj = models.Authors.objects.filter(pk=1).first() author_obj1 = models.Authors.objects.filter(pk=2).first() author_obj2 = models.Authors.objects.filter(pk=3).first() print(author_obj) # Authors object print(author_obj.name) # 張三 # 3、給獲取到的書籍添加一個作者對象 book_obj.authors.add(author_obj) book_obj.authors.add(author_obj1,author_obj2) ''' 總結:add給第三張表關係添加數據 括號內既可以傳數字也可以傳對象,並且都支持多個 '''
-
數據的刪除
# 刪除 remove # 方式一 book_obj = models.Book.objects.filter(pk=2).first() book_obj.authors.remove(2) # 刪除書籍主鍵值是2的,並且作者主鍵是2的作者 book_obj.authors.remove(1,3) # 刪除書籍主鍵值是2的,並且作者主鍵是1和3的作者 # 方式二 # 1、獲取書籍id爲2的書籍 book_obj = models.Book.objects.filter(pk=2).first() # 2、獲取到作者表中的主鍵值爲2/3的數據對象 author_obj = models.Authors.objects.filter(pk=2).first() author_obj1 = models.Authors.objects.filter(pk=3).first() # 3、刪除獲取到的作者 book_obj.authors.remove(author_obj,author_obj1) ''' 總結:remove 括號內既可以傳數字也可以傳對象,並且都支持多個 '''
-
數據的修改
# 修改 set 修改的值必須是一個可迭代對象 # 方式一 book_obj = models.Book.objects.filter(pk=2).first() book_obj.authors.set([1, 2]) # 括號內必須給一個可迭代對象 book_obj.authors.set([3]) # 括號內必須給一個可迭代對象 # 方式二 # 1、獲取書籍id爲2的書籍 book_obj = models.Book.objects.filter(pk=2).first() # 2、獲取到作者表中的主鍵值爲2/3的數據對象 author_obj = models.Authors.objects.filter(pk=2).first() author_obj1 = models.Authors.objects.filter(pk=3).first() # 3、修改獲取到的作者對象 book_obj.authors.set([author_obj, author_obj1]) # 括號內必須給一個可迭代對象 ''' 總結:set 括號內必須傳一個可迭代對象,既可以傳數字也可以傳對象,並且都支持多個 '''
-
數據的清空
# 清空 在第三張關係表中的清空某一個書籍與作者的綁定關係 clear book_obj.authors.clear() ''' 總結:clear 括號內不要加任何參數 '''
正反向的概念
正向:
外鍵字段在我手上,那麼我查你就是正向
反向:
外鍵字段不在我手上,那麼我查你就是反向
# book >>> 外鍵字段在書哪裏(正向) >>> publish # publish >>> 外鍵字段在書哪裏(反向) >>> book ''' 正向查找按字段,反向查找按表名(小寫)加_set '''
跨表查詢(重點)
子查詢(基於對象的跨表查詢)
# 查詢書籍主鍵爲2的出版社(書查出版社,主鍵字段在書這邊,正向) book_obj = models.Book.objects.filter(pk=2).first() res = book_obj.publish print(res,res.name) # Publish object 東方出版社 # 查詢書籍主鍵爲2的作者(書查作者,主鍵字段在書這邊,正向) book_obj = models.Book.objects.filter(pk=2).first() res = book_obj.authors.all() print(res) # <QuerySet [<Authors: Authors object>, <Authors: Authors object>, <Authors: Authors object>]> # 查詢作者張三的電話號碼(作者查作者詳情,主鍵字段在作者這邊,正向) author_obj = models.Authors.objects.filter(name='張三').first() res = author_obj.author_detail print(res) # AuthorDetail object print(res.phone) # 123 ''' 建議: 寫ORM語句與SQL語句類似,不要想的一次性寫完,可以寫一點看一點 正向什麼時候需要用到all(): 當結果可能有多個的時候需要加.all() (多對多關係) 當結果爲一個的時候,則直接拿到數據對象,無需.all() (一對一,一對多) ''' # 查詢出版社是北方出版社出版的書籍(出版社查書,主鍵字段在書這邊,反向) publish_obj = models.Publish.objects.filter(name='北方出版社').first() res = publish_obj.book_set # app01.Book.None res = publish_obj.book_set.all() # <QuerySet [<Book: Book object>]> print(res) # 查詢作者是張三寫過的書(作者查書,主鍵字段在書這邊,反向) author_obj = models.Authors.objects.filter(name='張三').first() res = author_obj.book_set.all() print(res[1].title) # <QuerySet [<Book: Book object>, <Book: Book object>, <Book: Book object>]> # 查詢手機號碼是123的作者姓名(作者詳情查詢作者,主鍵字段在作者這邊,反向) author_detail_obj = models.AuthorDetail.objects.filter(phone='123').first() res = author_detail_obj.authors # Authors object print(res) ''' 反向查詢什麼時候需要加_set.all(): 當查詢結果可能是多個時就必須加_set.all() (一對多,多對多) 當查詢結果只有一個時,不需要加_set.all() (一對一) '''
聯表查詢(基於雙下劃線的跨表查詢)
# 查詢張三的手機號和作者姓名 # 正向 res = models.Authors.objects.filter(name='張三').values('name','author_detail__phone') print(res) # <QuerySet [{'name': '張三', 'author_detail__phone': 123}]> # 反向 res = models.AuthorDetail.objects.filter(authors__name='張三').values('authors__name','phone') print(res) # <QuerySet [{'authors__name': '張三', 'phone': 123}]> # 查詢書籍主鍵爲2的出版社名稱和書的名稱 # 正向 res = models.Book.objects.filter(pk=2).values('publish__name','title') print(res) # <QuerySet [{'publish__name': '東方出版社', 'title': '三國演義'}]> # 反向 res = models.Publish.objects.filter(book__pk=2).values('name','book__title') print(res) # <QuerySet [{'name': '東方出版社', 'book__title': '三國演義'}]> # 查詢書籍主鍵爲2的作者姓名 # 正向 res = models.Book.objects.filter(pk=2).values('authors__name') print(res) # <QuerySet [{'authors__name': '張三'}, {'authors__name': '李四'}, {'authors__name': '王五'}]> # 反向 res = models.Authors.objects.filter(book__pk=2).values('name') print(res) # <QuerySet [{'name': '張三'}, {'name': '李四'}, {'name': '王五'}]> # 查詢書籍主鍵爲2的作者手機號碼 # 正向 res = models.Book.objects.filter(pk=2).values('authors__author_detail__phone') print(res) # <QuerySet [{'authors__author_detail__phone': 123}, {'authors__author_detail__phone': 456}, {'authors__author_detail__phone': 789}]> # 反向 res = models.AuthorDetail.objects.filter(authors__book=2).values('phone') print(res) # <QuerySet [{'phone': 123}, {'phone': 456}, {'phone': 789}]>