Django的學習進階(三)————ORM
django框架是將資料庫資訊進行了封裝,採取了
類——>資料表
物件——>記錄
屬性——>欄位
通過這種一一對應方式完成了orm的基本對映
官方文件:https://docs.djangoproject.com/en/2.2/
一、表單
models中每一個繼承於models.Model的類就是一張資料表
如:class AddressInfo就是一張關於地址的資料表
官方文件:https://docs.djangoproject.com/en/2.2/topics/db/models/
二、欄位
文件地址:https://docs.djangoproject.com/en/2.2/ref/models/fields/
1.自增長欄位(default=int)
# 自增長欄位 Auto = models.AutoField() # 預設為整型 BigAuto = models.BigAutoField() # 比Auto大
2.二進位制的資料
# 二進位制欄位 Binary = models.BinaryField() # 二進位制欄位
3.boolean型別
# Boolean型別 Boolean = models.BooleanField() # 不為空 NullBoolean = models.NullBooleanField() # 為空
4.整型
# 整型 PositiveSmallInteger = models.PositiveSmallIntegerField() # 能存取五個位元組的大小 SmallInteger = models.SmallIntegerField() # 能存取六個位元組的大小 可以是正整數也可以是負整數 PositiveInteger = models.PositiveIntegerField() # 10個位元組大小的正整數 Integer = models.IntegerField() # 11個位元組大小的正整數 BigInteger = models.BigIntegerField() # 20個位元組大小的整形
5.字元型
# 字串型別 Char = models.CharField() # varchar Text = models.TextField() # longtext
6.時間型別
# 時間日期型別 Date = models.DateField() # 年月日 DateTime = models.DateTimeField() # 年月日時分秒 Duration = models.DurationField() # 一段時間 int 底層用Python timedelta實現
7.浮點型
# 浮點型 Float = models.FloatField() # 浮點型 Decimal = models.DecimalField() # 需要指定整數多少位 小數多少位
8.其他欄位
# 其他欄位 Email = models.EmailField() # 郵箱 Image = models.ImageField() # 圖片 File = models.FileField() # 檔案 FilePath = models.FilePathField() # 檔案路徑 URL = models.URLField() # 網址 UUID = models.UUIDField() # 通用唯一識別碼 GenericIpAddress = models.GenericIPAddressField() # ip地址 ipv4的地址 或者是ipv6的地址
(2)欄位引數設計
1.通用引數
# db_column="" 指定在資料庫中的引數 # primary_key=True 設定主鍵 True # verbose_name="" 設定別名 # unique=True 設定欄位是否唯一 # null=True, blank=True, db_index=True null是表中的欄位是否為空 blank是表單提交的資料要和null保持一致 否則就會出現錯誤 同時給欄位建立索引 # help_text="" 建立幫助文件 # editable=False 使使用者不可以修改
2.個別引數具有的欄位
# Char型別: max_length 指定最大長度 # date型別: unique_for_date=True 設定日期必須唯一 還有月和年 # date型別: auto_now_add=True 增加記錄時的時間 插入資料的時間 # date型別: auto_now=True 更新當前記錄的時間 更新資料的時間 # Decimal型別: max_digits=4 總共多少位, decimal_places=2 小數的位數
3.關係型欄位
# related_name='' 外來鍵查詢的資訊 # on_delete: 當外來鍵不在的時候進行什麼操作 作為關係型欄位的必須引數(預設順序是外來鍵表to和on_delete) # on_delete的六種模式 """ models.CASCADE: 刪除級聯 A表記錄被刪除B表記錄也會被刪除 預設 要設定null=True blank=True models.PROTECT: 刪除時 會報PROTECT ERROR異常 models.SET: 傳一個SET值或者回調函式值 models.SET_NULL: 刪除置空 父表記錄被刪除子表記錄設定成NULL 同時需要指定null=True blank=True models.SET_DEFAULT: 當父表字段被刪除的時候我們給子表字段設定一個預設值 用default引數指定值 models.DO_NOTHING: 當父表被刪除子表什麼也不做 """
(3)關聯關係
關聯關係分為三種:一對一,一對多,多對多
1.基類
class Teacher(models.Model): # 教師類 objects = models.Manager() class Meta: verbose_name = "講師資訊表" verbose_name_plural = verbose_name def __str__(self): return self.nickname
2.一對一
其中的to和on_delete是必須引數,且要設計null和blank都要為空
class TeacherAssistant(models.Model): # 助教類 objects = models.Manager() # 外來鍵關聯 # 一對一 助教和教師 teacher = models.OneToOneField(to=Teacher, null=True, blank=True, on_delete=models.SET_NULL, verbose_name="講師")
2.一對多
其中的to和on_delete是必須引數,且要設計null和blank都為空
class Course(models.Model): objects = models.Manager() # 外來鍵關聯 # 一對多 一個講師對應多個課程 # 其中to和on_delete是必須引數 teacher = models.ForeignKey(to=Teacher, null=True, blank=True, on_delete=models.CASCADE, verbose_name='課程講師')
3.多對多
其中的to是必須引數
class Student(models.Model): # 學生類 objects = models.Manager() # 外來鍵關聯 # 多對多 學生和課程 course = models.ManyToManyField(to=Course, verbose_name='課程資訊')
(4)自關聯
利用自關聯的特性構建一個類似於省市縣的方法
關聯的時候可以使用‘self’或者是模型名
class AddressInfo(models.Model): address = models.CharField(max_length=200, null=True, blank=True, verbose_name='地址') pid = models.ForeignKey('self', models.CASCADE, null=True, blank=True, verbose_name='自關聯') # pid = models.ForeignKey('AddressInfo', null=True, blank=True, verbose_name='自關聯') def __str__(self): return self.address
三、元資料
文件地址:https://docs.djangoproject.com/en/2.2/ref/models/options/
設定資料庫的表名等資訊,對資料進行一個操作等
一些meta中的例項,官網有更多的欄位介紹和更加詳細的欄位資訊
class AddressInfo(models.Model): class Meta: ordering = ['pid'] # 指定按照什麼 欄位進行排序:-pid 是降序 沒有-表示升序 新增欄位的順序表示排序的先後結果 verbose_name = '省市縣' # 設定成一個直觀的名字在admin中 verbose_name_plural = verbose_name # 設定成複數 abstract = True # 不生成資料表 作為其他類的基類 permissions = [('定義好的許可權', '給許可權的說明'), ] # 二元的列表或者是元組 managed = False # 是否按照Django既定的模型類管理 比如是否建立資料表 unique_together = [] # 聯合唯一鍵, 可以使用一元列表:只使用一組欄位作為約束條件 二元列表:[[], []] db_table = 'address' # 修改資料庫的表名 app_label = 'app_name' # 定義模型類屬於哪一個應用, 在app沒有新增到setting的配置環境中 db_tablespace = 'db_tablespace_name' # 定義資料庫表空間的名字
四、Django的資料表
(1)models生成流程
1.資料表的程式碼
class Teacher(models.Model): nickname = models.CharField(max_length=30, primary_key=True, db_index=True, verbose_name='暱稱', ) introduction = models.TextField(default="這位同學很懶,什麼也沒有留下來", verbose_name="簡介", ) fans = models.PositiveIntegerField(default=0, verbose_name="粉絲數") create_date = models.DateField(auto_now_add=True, verbose_name='建立時間', ) update_date = models.DateField(auto_now=True, verbose_name='更新時間', ) objects = models.Manager() class Meta: verbose_name = "講師資訊表" verbose_name_plural = verbose_name def __str__(self): return self.nickname class Course(models.Model): title = models.CharField(max_length=100, primary_key=True, db_index=True, verbose_name="課程名") course_type = models.CharField(choices=((0, '其他'), (1, "實戰課"), (2, "免費課程")), max_length=1, default=0, verbose_name="課程型別") price = models.PositiveSmallIntegerField(verbose_name="價格") volume = models.BigIntegerField(verbose_name="銷量") online = models.DateField(verbose_name="上線時間") create_date = models.DateField(auto_now_add=True, verbose_name='建立時間', ) # 系統自己新增 update_date = models.DateField(auto_now=True, verbose_name='更新時間', ) # 系統自己新增 objects = models.Manager() # 外來鍵關聯 # 一對多 一個講師對應多個課程 teacher = models.ForeignKey(to=Teacher, null=True, blank=True, on_delete=models.CASCADE, verbose_name='課程講師') class Meta: verbose_name = "課程資訊表" verbose_name_plural = verbose_name def __str__(self): # _get_FIELD_display可以展示Filed的型別 return f"{self._get_FIELD_display(self.course_type)}-{self.title}" class Student(models.Model): nickname = models.CharField(max_length=30, primary_key=True, db_index=True, verbose_name='暱稱', ) age = models.PositiveSmallIntegerField(verbose_name="年齡") gender = models.CharField(choices=((1, "男"), (2, "女"), (0, "保密")), max_length=1, default=0, verbose_name="性別") study_time = models.PositiveIntegerField(default=0, verbose_name="學習時長(h)") create_date = models.DateField(auto_now_add=True, verbose_name='建立時間', ) update_date = models.DateField(auto_now=True, verbose_name='更新時間', ) objects = models.Manager() # 外來鍵關聯 # 多對多 學生和課程 course = models.ManyToManyField(to=Course, verbose_name='課程資訊') class Meta: verbose_name = "學生資訊表" verbose_name_plural = verbose_name def __str__(self): return self.nickname class TeacherAssistant(models.Model): nickname = models.CharField(max_length=30, primary_key=True, db_index=True, verbose_name='暱稱', ) hobby = models.CharField(max_length=30, null=True, blank=True, verbose_name='愛好', ) create_date = models.DateField(auto_now_add=True, verbose_name='建立時間', ) update_date = models.DateField(auto_now=True, verbose_name='更新時間', ) objects = models.Manager() # 外來鍵關聯 # 一對一 teacher = models.OneToOneField(to=Teacher, null=True, blank=True, on_delete=models.SET_NULL, verbose_name="講師") class Meta: verbose_name = "講師助手資訊表" verbose_name_plural = verbose_name def __str__(self): return self.nicknameView Code
2.在對應的應用的migration中生成對應的migrations檔案
通過使用指令:【python manage.py makemigrations】完成資料的遷移,在對應的APP下面的migrations裡面生成遷移資料日誌
3.在django_migrations下面的生成記錄
通過指令:【python manage.py migrate】完成資料的建表資訊,將migrations裡面的資料日誌轉成資料庫語言存入資料庫中
4.在資料庫中生成的資料表
5.刪除資料表
因此再刪除的時候按照上面的四步就可以刪除一個models類
(2)匯入資料
1.Django-shell
使用【python manage.py shell】進入到命令列,匯入對應的類建立物件完成資料的儲存,【from [appname].models import [模板類]】
2.指令碼
按照sys、os——>配置環境檔案——>匯入Django——>匯入資料表.嚴格按照這個順序匯入資料資訊,否則就會報錯
其中settings前面的是專案的名字
參考blog:https://blog.csdn.net/qq_40999403/article/details/80694545
# -*- coding:utf-8 -*- # __author__ == pzq # @email: [email protected] import os import sys import random from datetime import date # 將django專案根目錄加入環境變數 parent_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.append(parent_path) # 引入django配置檔案 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "film.settings") # 啟動django import django django.setup() from index.models import Student, Course, TeacherAssistant, Teacher def import_data(): # 使用Django ORM匯入資料 # 講師資料 create() Teacher.objects.create(nickname='Jack', introduction="Python工程師", fans=random.randint(500, 1000)) Teacher.objects.create(nickname="Jerry", introduction="Java工程師", fans=random.randint(200, 800)) Teacher.objects.create(nickname="Peter", introduction="PHP工程師", fans=random.randint(400, 700)) Teacher.objects.create(nickname="Kate", introduction="C++工程師", fans=random.randint(100, 400)) # 課程資料 bulk_create() 批量匯入資料 # 外來鍵的連線通過物件 Course.objects.bulk_create([Course(title=f"python入門課程{i}", course_type=random.choice((0, 1, 2)), price=random.randint(100, 1000), volume=random.randint(1000, 10000), online=date(random.randint(2010, 2019), random.randint(1, 12), random.randint(1, 28)), teacher=Teacher.objects.get(nickname="Jack")) for i in range(1, 4)]) Course.objects.bulk_create([Course(title=f"Java入門課程{i}", course_type=random.choice((0, 1, 2)), price=random.randint(100, 1000), volume=random.randint(2000, 9000), online=date(random.randint(2010, 2019), random.randint(1, 12), random.randint(1, 28)), teacher=Teacher.objects.get(nickname="Jerry")) for i in range(1, 5)]) Course.objects.bulk_create([Course(title=f"PHP進階課程{i}", course_type=random.choice((0, 1, 2)), price=random.randint(100, 1000), volume=random.randint(1000, 4000), online=date(random.randint(2010, 2019), random.randint(1, 12), random.randint(1, 28)), teacher=Teacher.objects.get(nickname="Peter")) for i in range(1, 3)]) Course.objects.bulk_create([Course(title=f"C++高階課程{i}", course_type=random.choice((0, 1, 2)), price=random.randint(100, 1000), volume=random.randint(1000, 2000), online=date(random.randint(2010, 2019), random.randint(1, 12), random.randint(1, 28)), teacher=Teacher.objects.get(nickname="Kate")) for i in range(1, 4)]) # 學生資料 # update_or_create() 先通過nickname現在資料庫中找尋這個資料 如果存在就update如果不存在就create # 把主鍵或者唯一鍵放在外面 把其他引數放在裡面 Student.objects.update_or_create(nickname="A同學", defaults={"age": random.randint(18, 28), "gender": random.choice((0, 1, 2)), "study_time": random.randint(1000, 2000)}) Student.objects.update_or_create(nickname="B同學", defaults={"age": random.randint(18, 28), "gender": random.choice((0, 1, 2)), "study_time": random.randint(1000, 2000)}) Student.objects.update_or_create(nickname="C同學", defaults={"age": random.randint(18, 28), "gender": random.choice((0, 1, 2)), "study_time": random.randint(1000, 2000)}) Student.objects.update_or_create(nickname="D同學", defaults={"age": random.randint(18, 28), "gender": random.choice((0, 1, 2)), "study_time": random.randint(1000, 2000)}) # 接下來新增外來鍵欄位 # 正向新增 pk可以代替主鍵查詢 子表關聯到父表 # 銷量大於等於1000的課程 Student.objects.get(nickname="A同學").course.add(*Course.objects.filter(volume__gte=1000)) # 銷量大於5000的課程 Student.objects.get(nickname="B同學").course.add(*Course.objects.filter(volume__gt=5000)) # 反向新增 通過課程關聯到學生 # 學習時間大於等於500小時的同學 Course.objects.get(title="python入門課程1").student_set.add(*Student.objects.filter(study_time__gte=1500)) # 學習時間小於等於500小時的同學 Course.objects.get(title="python入門課程2").student_set.add(*Student.objects.filter(study_time__lte=1500)) # 助教資料 get_or_create() 先通過nickname的關鍵字或者是主鍵進行查詢 如果有就獲取沒有就建立 TeacherAssistant.objects.update_or_create(nickname="助教1", defaults={"hobby": "慕課網學習", "teacher": Teacher.objects.get(nickname="Jack")}) TeacherAssistant.objects.update_or_create(nickname="助教2", defaults={"hobby": "中國Mooc學習", "teacher": Teacher.objects.get(nickname="Jerry")}) TeacherAssistant.objects.update_or_create(nickname="助教3", defaults={"hobby": "程式設計師客棧", "teacher": Teacher.objects.get(nickname="Peter")}) TeacherAssistant.objects.update_or_create(nickname="助教4", defaults={"hobby": "牛客網", "teacher": Teacher.objects.get(nickname="Kate")}) return True if __name__ == '__main__': try: if import_data(): print("資料匯入成功!") except Exception as AddError: print(AddError)View Code
3.fixtures Django serialization ——> model 儲存到資料庫
使用指令【python manage.py dumpdata > film.json】輸出資料庫檔案
使用指令【python manage.py loaddata film.json】輸入資料到資料庫
4.通過資料庫層面來實現
匯入SQL檔案等
(3)匯出資料
1.mange.py dumpdata > [檔名]
2.使用pycharm或者是Navicat等資料工具來匯出
3.使用資料庫層面:MySQL dumpdata來實現
五、models API
queryset文件:https://docs.djangoproject.com/en/2.2/ref/models/querysets/
(1)查詢介紹
def start(request): """ int型別的操作函式: gte:大於等於 exact:等於 gt:大於 in:在某某之內 isnull:是否為空 lt:小於 lte:小於等於 range:在什麼範圍內 字元型更多:其中i是忽略大小寫敏感 """ # 1.查詢 檢索 過濾 # 返回的是物件 teacher = Teacher.objects.filter(fans__gte=500) # 是個query集 給欄位匹配資料的時候一定要用雙下劃線 # 其中pk是主鍵 在這裡就是nickname的關鍵字 t1 = Teacher.objects.get(pk="Jack") # get只能返回一條結果 所有采取主鍵或者是唯一鍵 t2 = Teacher.objects.all() # 查詢所有資料 返回所有資料的物件集 # # 2.欄位匹配大小寫敏感 t3 = Teacher.objects.filter(pk__icontains="A") # 有很多可以去檢視一下官網 # # 3.結果切片 排序 鏈式查詢 # 切片 t3_1 = Teacher.objects.all().order_by('-fans')[1:] # 排序 t4 = Teacher.objects.all().order_by('-fans') # -代表降序 按照老師的粉絲數進行排序 t4_1 = Teacher.objects.all().order_by('fans') # 預設升序 # # 鏈式查詢 t5 = Teacher.objects.filter(fans__gte=500).order_by('fans') # 先獲取一個欄位的屬性 在對獲取的資料集在採取升序排序 t6 = Teacher.objects.filter(fans__gte=500).order_by('-fans') # 先獲取一個欄位的屬性 在對獲取的資料集在採取降序排序 # 4.查詢原生sql語句 通過query進行查詢 print(f"我是查詢語句{str(t6.query)}") return render(request, 'learn_set.html')View Code
(2)返回新的queryset的API
def start(request): """ 查詢介紹 返回新的 Query API """ # 1.all() filter() order_by():排序 exclude():除了xx元素以外 reverse():反向排序 distinct():去重 # 可以用pk代替關鍵字 exclude除去含有關鍵字的資訊 st_0 = Student.objects.all().exclude(pk="A同學") # print(f"我是exclude:{st_0}") # 使用reverse的時候可以在Meta中用ordering指定排序的欄位 多個ordering的時候取第一個 預設按照關鍵字的順序輸出 st_0_1 = Student.objects.reverse() # print(f"我是reverse:{st_0_1}") # 2.extra():給欄位取別名 defer():排除一些欄位 only():選擇一些欄位 # extra(): extra(select={"[要取的別名]": "[原來欄位名]"}) st_1 = Student.objects.all().extra(select={"name": "nickname"}) # for i in st_1: # print(f"我是extra:{i.name}") st_2 = Student.objects.all().only('nickname', 'age') # print(f"我是only_query:{str(st_2.query)}") # 3.values():字典 values_list():元組 獲取字典或者是元組形式的queryset # values() 輸出的是dict型別的 st_3_0 = TeacherAssistant.objects.values('nickname', 'hobby') # print(f"我是values:{st_3_0}") # values_list() 輸出的是元組型別的資料 st_3_1 = TeacherAssistant.objects.values_list('nickname', flat=True) # flat:將單個欄位的資料直接放到列表裡面 只限於獲取單個數據的資訊 # print(f"我是values_list:{st_3_1}") # 4.根據時間和日期獲取查詢集 dates:年月日 datetimes年月日時分秒查詢欄位多一點有時分秒 使用什麼查詢方式取決於定義欄位的型別 # datetimes('[查詢時間的欄位]', 'month', order='DESC') st_4 = Course.objects.dates('online', 'year', order='DESC') # ASC 升序排列(預設) DESC降序排列 # print(f"我是dates:{st_4}") # 5.集合的運算 union():並集 intersection():交集 difference():差集 s_1 = Student.objects.filter(study_time__gte=1600) # 大於等於1500 s_2 = Student.objects.filter(study_time__lte=1500) # 小於等於1600 # print(f"我是union:{s_1.union(s_2)}") # 只支援取並集 # print(f"我是intersection:{s_1.intersection(s_2)}") # 資料庫不支援 # print(f"我是difference:{s_1.difference(s_2)}") # 資料庫不支援 # 6.優化查詢api select_related() 一對一 多對一的優化查詢 prefetch_related() 一對多 多對多的優化查詢 # select_related() # 通過課程獲取講師資訊 查詢相關資訊通過外接欄位進行連線 c_1 = Course.objects.all().select_related('teacher') for c in c_1: print(f"課程資訊:{c.title}--{c.teacher.nickname}--{c.teacher.fans}") # prefetch_related() 多對多 s_1 = Student.objects.filter(age__lte=30).prefetch_related('course') for s in s_1: for i in s.course.all(): # 獲取到的是managerelmanage的物件 print(f"{s.nickname}--{i.title}") # 輸出課程的資訊 # 反向查詢:根據父表查詢子表 # 通過在資料段的對應關係 [字表的表名]_set可以替換為related_name的值 t_1 = Teacher.objects.get(nickname='Jack').teach.all() print(f"我是反向查詢{t_1}") # 7.annotate() 使用聚合計數、求和、平均數、raw()、執行原生的SQL # 求和 sum_1 = Course.objects.values('[處理表單]').annotate(vol=Sum('[處理欄位]')) sum_1 = Course.objects.values('teacher').annotate(vol=Sum('volume')) print(f"我是求和:{sum_1}") # 平均值 ave_1 = Student.objects.values('course').annotate(time=Avg('study_time')) print(f"我是求平均值:{ave_1}") # row可以寫原生資料語句 裡面執行原生的SQL語句 # 參考文件 # https://docs.djangoproject.com/en/2.2/topics/db/sql/View Code
(3)不返回新的query的API
def start(request): """ 不返回查詢集的API """ # 參考文件:https://docs.djangoproject.com/en/2.2/ref/models/querysets/#raw # 1.獲取物件 get() get_or_create() first() last() latest() earliest() in_bulk() # get() 獲取物件 # get_or_create() 有資料就通過get獲取沒有就建立資料 # first() # 第一條記錄 # print(f"我是first:{Course.objects.first()}") # last() # 最後一條記錄 # print(f"我是last:{Course.objects.last()}") # latest() # 最近的記錄 需要在模型類裡面設定 get_latest_by = [建立的欄位] 代表根據建立的欄位進行排序 # 也可以在排序的時候自己指定 更加方便我們自己的操作 # print(f"我是latest{Course.objects.latest('online')}") # earliest() # 最早的記錄 # print(f"我是earliest{Course.objects.earliest('update_date')}") # in_bulk() 批量返回物件 根據主鍵的值傳遞一個列表 列表中傳遞主鍵的值 # print(Course.objects.in_bulk(['Java入門課程1', 'Java入門課程2', 'python入門課程2'])) # 2.建立物件 create():建立物件 bulk_create():批量建立物件 create_or_update():如果沒有就建立有就更新 # bulk_create:給函式建立一個列表 # 3.更新物件 update():更新 update_or_create():更新或建立 # update() # print(f"我是更新前的價格:{Course.objects.get(title='C++高階課程1').price}") # Course.objects.filter(title="C++高階課程1").update(price=568) # print(f"我是更新後的價格:{Course.objects.get(title='C++高階課程1').price}") # 4.刪除物件 delete():使用filter過濾 # print(Course.objects.filter(title="test_1").delete()) # 5.其他操作 exist():是否存在 count():統計個數 aggregate():聚合 # exist() # print(Course.objects.filter(title="test_1").exists()) # print(Course.objects.filter(title="PHP進階課程2").exists()) # count()記錄資料表中的資料個數 # print(Course.objects.count()) # annotate():和value配合使用 對分組結果進行排序 aggregate():對資料庫中的資料結果進行處理 # print(Course.objects.aggregate(Max('price'), Min('price'), Avg('price'), Sum('volume'))) return render(request, 'learn_set.html')View Code
(4)自定義聚類查詢
1.自定義查詢方法
在individual.py中加入以下程式碼
from django.db import models class Concat(models.Aggregate): """ORM用來分組顯示其他欄位 相當於group_concat""" function = 'GROUP_CONCAT' template = '%(function)s(%(distinct)s%(expressions)s)' def __init__(self, expression, distinct=False, **extra): super(Concat, self).__init__( expression, distinct='DISTINCT ' if distinct else '', output_field=models.CharField(), **extra)
2.引用
在views.py中的引用
from .individual import Concat def start(request): """ 自定義聚合查詢 """ # 這個title對應查詢結果中的key Concat裡面的才是我們需要查詢的欄位 course = Course.objects.values('teacher').annotate(title=Concat('title')) for c in course: print(c) return render(request, 'learn_set.html')
(5)F物件查詢
官方文件:https://docs.djangoproject.com/en/2.2/ref/models/expressions/#django.db.models.F
def start(request): """ F查詢 """ # 操作欄位資料或者是將一個欄位與另一個欄位進行比較 # # 將所有的價格減11 # Course.objects.update(price=F('price') - 11) # # 獲取銷量大於價格10倍的欄位 # course = Course.objects.filter(volume__gte=F('price') * 10) # for c in course: # print(f"{c.title}--{c.price}--{c.volume}") return render(request, 'learn_set.html')
(6)Q物件查詢
官方文件:https://docs.djangoproject.com/en/2.2/ref/models/querysets/#q-objects
def start(request): """ Q物件結合 &:and |:or :not 實現複雜的查詢 """ # 查詢所有Java課程 並且銷量大於等於5000 print(Course.objects.filter(Q(title__icontains='java') & Q(volume__gte=5000))) # 查詢所有Python語言或者是銷量小於2000的課程 print(Course.objects.filter(Q(title__icontains='python') | Q(volume__lte=2000))) return render(request, 'learn_set.html')
(7)模型類例項:
class Teacher(models.Model): nickname = models.CharField(max_length=30, primary_key=True, db_index=True, verbose_name='暱稱', ) introduction = models.TextField(default="這位同學很懶,什麼也沒有留下來", verbose_name="簡介", ) fans = models.PositiveIntegerField(default=0, verbose_name="粉絲數") create_date = models.DateField(auto_now_add=True, verbose_name='建立時間', ) update_date = models.DateField(auto_now=True, verbose_name='更新時間', ) # 每一個非抽象model類必須Manager新增一個例項 objects = models.Manager() class Meta: verbose_name = "講師資訊表" verbose_name_plural = verbose_name def __str__(self): return self.nickname class Course(models.Model): title = models.CharField(max_length=100, primary_key=True, db_index=True, verbose_name="課程名") course_type = models.CharField(choices=((0, '其他'), (1, "實戰課"), (2, "免費課程")), max_length=1, default=0, verbose_name="課程型別") price = models.PositiveSmallIntegerField(verbose_name="價格") volume = models.BigIntegerField(verbose_name="銷量") online = models.DateField(verbose_name="上線時間") create_date = models.DateField(auto_now_add=True, verbose_name='建立時間', ) # 系統自己新增 update_date = models.DateField(auto_now=True, verbose_name='更新時間', ) # 系統自己新增 objects = models.Manager() # 外來鍵關聯 # 多對一 多個課程對應一個講師 teacher = models.ForeignKey(to=Teacher, null=True, blank=True, on_delete=models.CASCADE, verbose_name='課程講師', related_name='teach') class Meta: verbose_name = "課程資訊表" verbose_name_plural = verbose_name # 根據建立的欄位進行排序 方便latest和earliest進行排序 也可以在排序時指定 # get_latest_by = 'online' def __str__(self): # get_[要展示的欄位]_display()就可以輸出了 如2--python入門課程1>, return f"{self.get_course_type_display()}--{self.title}" class Student(models.Model): nickname = models.CharField(max_length=30, primary_key=True, db_index=True, verbose_name='暱稱', ) age = models.PositiveSmallIntegerField(verbose_name="年齡") gender = models.CharField(choices=((1, "男"), (2, "女"), (0, "保密")), max_length=1, default=0, verbose_name="性別") study_time = models.PositiveIntegerField(default=0, verbose_name="學習時長(h)") create_date = models.DateField(auto_now_add=True, verbose_name='建立時間', ) update_date = models.DateField(auto_now=True, verbose_name='更新時間', ) objects = models.Manager() # 外來鍵關聯 # 多對多 學生和課程 course = models.ManyToManyField(to=Course, verbose_name='課程資訊') class Meta: # 指定多個時 按第一個進行排序 # 不指定根據關鍵字的順序進行排序 如在資料表中新增的資料順序 ordering = ['study_time'] verbose_name = "學生資訊表" verbose_name_plural = verbose_name def __str__(self): return self.nickname class TeacherAssistant(models.Model): nickname = models.CharField(max_length=30, primary_key=True, db_index=True, verbose_name='暱稱', ) hobby = models.CharField(max_length=30, null=True, blank=True, verbose_name='愛好', ) create_date = models.DateField(auto_now_add=True, verbose_name='建立時間', ) update_date = models.DateField(auto_now=True, verbose_name='更新時間', ) objects = models.Manager() # 外來鍵關聯 # 一對一 如果on_delete置空就要將null, blank都設定為空 teacher = models.OneToOneField(to=Teacher, null=True, blank=True, on_delete=models.SET_NULL, verbose_name="講師") class Meta: verbose_name = "講師助手資訊表" verbose_name_plural = verbose_name def __str__(self): return self.nicknameView Code
六、總結
本篇blog簡單的介紹了orm的內容,也是Django後端內容中最為重要的一個部分,其他詳情請參考Django的官方文件
&n