PythonWeb開發基礎教程-第4章-模型和數據庫課件_第1頁
PythonWeb開發基礎教程-第4章-模型和數據庫課件_第2頁
PythonWeb開發基礎教程-第4章-模型和數據庫課件_第3頁
PythonWeb開發基礎教程-第4章-模型和數據庫課件_第4頁
PythonWeb開發基礎教程-第4章-模型和數據庫課件_第5頁
已閱讀5頁,還剩105頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、Python Web開發基礎教程(Django版)第4章 模型和數據庫本章主要內容:模型基礎數據操作索引特殊查詢表達式執行原始SQL查詢關系4.1模型基礎 模型是項目的數據來源。每個模型都是一個Python類,并且映射到一個數據庫表。模型的每個屬性相當于數據庫表的一個字段。使用模型對象可完成各種數據庫表操作。本節主要內容定義模型模型配置遷移數據庫定義字段4.1.1定義模型定義模型就是實現一個django.db.models.Model類的子類。模型的文件名稱默認為models.py,也可使用其他名稱。實例:創建項目chapter4和應用faqs,在應用faqs中定義模型類faqsdata。具體

2、操作步驟:演示4.1.2模型配置要使用模型,還需要在項目配置文件settings.py中完成相應的設置。首先,需要在項目配置文件的INSTALLED_APPS變量中添加包含模型的應用名稱,代碼如下。INSTALLED_APPS = , faqs, 其次,需要在項目配置文件的DATABASES變量中設置數據庫信息,項目默認的數據庫配置信息如下。DATABASES = default: ENGINE: django.db.backends.sqlite3, NAME: os.path.join(BASE_DIR, db.sqlite3), MySQL數據庫的配置如下。DATABASES = def

3、ault: ENGINE: django.db.backends.mysql, NAME: mysqldb, USER: sqldbuser1, PASSWORD: sqldbpassword1, HOST: , PORT: , Oracle數據庫的配置如下。DATABASES = default: ENGINE: django.db.backends.oracle, NAME: myordb, USER: ordbuser1, PASSWORD: ordbpassword1, HOST: 127.0.0.1, PORT: 1540, PostgreSQL數據庫的配置如下。DATABASES

4、= default: ENGINE: django.db.backends.postgresql, NAME: mypsdb, USER: psdbuser1, PASSWORD: psdbpassworda1, HOST: 127.0.0.1, PORT: 5432, 4.1.3遷移數據庫完成模型的定義和配置后,在使用數據庫之前,還需執行數據庫遷移操作。Django通過遷移操作將模型的更改(模型定義、模型刪除、字段更改等)應用到數據庫。首先,執行makemigrations命令,根據模型的更改情況生成遷移文件。E:chapter4python manage.py makemigrations

5、生成遷移文件后,執行migrate命令,應用遷移文件完成遷移操作E:chapter4python manage.py migrate4.1.4定義字段字段的定義包括字段名、字段類型和字段選項示例代碼如下。question=models.CharField(max_length=200,blank=True)其中,question為字段名,CharField為字段類型,max_length和blank為字段選項。Django在django.db.models.fields模塊中定義了可用的字段類型。為了方便,Django已將fields模塊導入到django.db.models模塊中。通常,先用

6、from django.db import models 導入models模塊,然后用models.xxxField來引用字段類型。表4-1字段類型字段類型說明AutoField自動增量,32位整數,取值范圍是1231-1BigAutoField自動增量,64位整數,取值范圍是1263-1BigIntegerField64位整數,取值范圍是-263263-1。字段的默認表單控件為TextInputBinaryField存儲原始二進制數據BooleanField存儲True或False。字段的默認表單控件為CheckboxInputCharField存儲字符串。字段的默認表單控件為TextInp

7、utDateField存儲日期,字段值為datetime.date實例。字段的默認表單控件為TextInputDateTimeField存儲日期時間,字段值為datetime.datetime實例。字段的默認表單控件為TextInputDecimalField存儲固定精度的十進制數字段,字段值為Decimal實例。字段的默認表單控件為NumberInputDurationField存儲時間段EmailField存儲E-mail地址FileField存儲文件。字段的默認表單控件為ClearableFileInputFilePathField存儲文件路徑FloatField存儲浮點數字。字段的默認

8、表單控件為NumberInputImageField存儲圖片。字段的默認表單控件為ClearableFileInput表4-1字段類型(續)字段類型說明IntegerField存儲整數。取值范圍是-231231-1。字段的默認表單控件為NumberInputGenericIPAddressField存儲字符串格式的IPv4或IPv6地址。字段的默認表單控件為TextInputPositiveIntegerField存儲非負整數。取值范圍是0231-1PositiveSmallIntegerField存儲非負小整數。取值范圍是0215-1SlugField存儲Slug數據,只包含字母、數字、下劃

9、線或連字符SmallIntegerField存儲小整數。取值范圍是-215215-1TextField存儲大量文本。字段的默認表單控件為TextareaTimeField存儲時間,字段值為datetime.time實例。字段的默認表單控件為TextInputURLField存儲URL。字段的默認表單控件為TextInputUUIDField存儲唯一標識符,字段值為UUID類實例表4-2字段選項選項說明null默認為False。為True時,Django在字段無數據時將空值NULL存入數據庫(字符串字段存入空字符串)blank默認為False。為True時,字段允許為空,即表單驗證將允許輸入空值

10、。blank影響數據驗證,null影響數據庫數據存儲choices為字段定義選擇項。字段值為選擇項中的列表或元組中的值db_column定義字段在數據庫表中的列名稱。未設置時,Django用模型中的字段名作為數據庫表列名稱db_index為True時,為該字段創建數據庫索引db_tablespace若為字段創建了索引,則為字段索引設置數據庫的表空間名稱default設置字段默認值editable默認是True。為False時,字段不在模型表單中顯示error_messages設置錯誤提示信息。該設置會覆蓋默認的錯誤提示信息help_text設置字段的幫助信息primary_key設置為True

11、時,字段成為模型的主鍵。unique設置為True時,字段值在整個表中必須是唯一的unique_for_date設置為日期或日期時間字段名,關聯的兩個字段值在整個表中必須是唯一的unique_for_month類似unique_for_date。與關聯的月份唯一unique_for_year類似unique_for_date。與關聯的年份唯一verbose_name為字段設置備注名稱validators為字段設置校驗器4.2 數據操作在完成模型定義和數據庫遷移操作后,數據庫中有了與模型一致的表,便可進一步執行數據操作,包括添加數據、獲取數據、更新數據和刪除數據。也可使用可視化工具(如Visua

12、l Studio)來管理數據。本節主要內容在Visual Studio中管理SQLite數據庫添加數據獲取數據字段查找更新數據刪除數據查詢集操作4.2.1在Visual Studio中管理SQLite數據庫使用第三方組件dotConnect for SQLite,可在Visual Studio中管理SQLite數據庫。1安裝件dotConnect for SQLite2連接到SQLite數據庫Visual Studio使用服務器資源管理器管理服務器和數據連接。3檢索數據鼠標右鍵單擊要查看數據的表(如faqs_faqsdata),然后選擇“檢索數據”命令,可打開查詢設計器窗口。查詢設計器窗口默認

13、顯示了表的數據,可在其中修改、添加或刪除數據。修改數據:在表格中直接修改現有數據,修改后按【Enter】鍵或單擊當前行之外的任意位置,數據自動完成保存。添加數據:表格最下方為添加數據行,在其中輸入數據即可添加一條新記錄。注意:自動增量字段(如Django自動添加的id字段)不需要輸入值。刪除數據:單擊每行左側的選擇按鈕,選中該行。再用鼠標右鍵單擊該行任意位置,在彈出的快捷菜單中選擇“刪除”命令,打開確認對話框。在對話框中單擊“是”按鈕刪除選中的行。4.2.2添加數據添加數據的基本步驟:首先創建模型對象,再調用save()方法將對象數據寫入數據庫E:chapter4python manage.p

14、y shell #進入當前項目的Python交互環境 from faqs.models import faqsdata #導入模型類 d=faqsdata(question=test,answer=bbb)#創建模型對象 d.save()#執行保存操作,將數據寫入數據庫 d.id,d.question,d.answer#查看字段值(1, test, bbb)create()方法可用于創建對象,同時執行保存操作示例如下。 d=faqsdata.objects.create(question=test3,answer=test3)#創建對象,并將數據存入數據庫 d.id4Django通過Manag

15、er(模型管理器)提供數據庫訪問接口。默認情況下,Django為每個模型添加一個名為objects的管理器,調用objects的各種方法可完成相關的數據庫操作。在使用模型對象添加數據時,應注意默認的id字段。Django自動為模型添加一個名為id的自動增量字段,將其作為模型的主鍵。應注意的是,在創建了模型對象后,調用save()保存數據之前,id字段值是空值示例代碼如下。 d4=faqsdata(question=test4,answer=test4)#創建對象 d4.id#查看id字段值,輸出結果為空 d4.questiontest4 d4.save()#保存對象到數據庫 d4.id#id字

16、段有值5在創建模型對象時,也可指定自動增量字段id的值,例如: d=faqsdata(id=5,question=test8,answer=aaa)注意,如果指定的id值與數據庫表中已有的id值相同,則會用新數據覆蓋原數據。4.2.3獲取數據Django通過模型對象的默認模型管理器objects提供了多種獲取數據的方法。1獲取所有數據行all()方法返回數據表中的所有數據。all()方法相當于SQL中的“SELECT * FROM ”命令,示例代碼如下。 ds=faqsdata.objects.all()#獲取全部數據行 for a in ds:#迭代,輸出全部數據. print(a.id,a

17、.question,a.answer).3 test bbb4 test3 test35 test8 aaa其中,faqsdata.objects.all()相當于“SELECT * FROM faqs_faqsdata”。2獲取排序數據order_by()方法返回按指定字段排序的結果示例代碼如下。 ds=faqsdata.objects.order_by(answer)#返回按answer字段排序的數據 for a in ds:. print(a.id,a.question,a.answer).5 test8 aaa3 test bbb4 test3 test3其中,faqsdata.obj

18、ects.order_by(answer)相當于“SELECT * FROM faqs_faqsdata ORDER BY answer”。3篩選數據filter()方法按指定條件篩選數據,示例代碼如下。 ds=faqsdata.objects.filter(question=test) for a in ds:. print(a.id,a.question,a.answer).3 test bbb其中,faqsdata.objects.filter(question=test)相當于“SELECT * FROM faqs_faqsdata WHERE question=test”。exclu

19、de()方法與filter()方法相反,它返回不滿足條件的數據示例代碼如下。 ds=faqsdata.objects.exclude(question=test) for a in ds:. print(a.id,a.question,a.answer).4 test3 test35 test8 aaa其中,faqsdata.objects.exclude (question=test)相當于“SELECT * FROM faqs_ faqsdata WHERE not question=test”。4獲取單個數據行get()方法按條件搜索單個數據行,返回結果為模型對象示例代碼如下。 d=fa

20、qsdata.objects.get(id=3) print(d.id,d.question,d.answer)3 test bbb如果給定的條件匹配多個數據行,則會觸發MultipleObjectsReturned異常。如果沒有找到匹配的數據行,則會觸發DoesNotExist異常。5values()和values_list()all()、order_by()、exclude()和filter()方法返回查詢集對象(QuerySet),查詢集對象用于迭代時,其成員是模型對象。每個模型對象封裝一條記錄。values()方法返回的查詢集在用于迭代時,其成員是字典對象,每個字典對象封裝一條記錄,示

21、例代碼如下。 ds=faqsdata.objects.exclude(question=test)#返回查詢集 ds#查看查詢集成員類型QuerySet , ds=faqsdata.objects.exclude(question=test).values()#返回封裝字典對象的查詢集 ds#查看查詢集成員類型可在values()方法的參數中指定查詢結果集包含的字段示例代碼如下。 faqsdata.objects.values()#不指定字段名時,包含全部字段 faqsdata.objects.values(id,question)包含指定字段values_list()和values()類似,

22、它返回的查詢結果集封裝的是元組,每個元組對應一條記錄示例代碼如下。 faqsdata.objects.values_list(id,question)4.2.4字段查找在filter()、exclude()和get()方法中,可使用Django提供的字段查找功能。字段查找表達式基本格式為“字段名_查找類型=表達式”,注意“字段名”和“查找類型”之間是兩個下劃線。例如: ds=faqsdata.objects.filter(id_in=3,5) #等同于SQL中的where id in (3,5) for a in ds:. print(a.id,a.question,a.answer).3 t

23、est bbb5 test8 aaa其中,faqsdata.objects.filter(id_in=3,5)相當于“SELECT * FROM faqs_faqsdata WHERE id in (3,5)”。表4-3字段查找類型查找類型說明exact完全符合。例如,question_exact=test等同于where question=test。與None比較時,SQL會將其解釋為NULL。例如,question_exact=None,等同于where question is NULLiexact與exact類似,但不區分字母大小寫contains包含,區分字母大小寫。例如,questi

24、on_contains =test等同于where question like %test%。(注意:不同數據庫中的like關鍵字用法可能有所不同。)icontains包含,不區分字母大小寫in在指定項中進行匹配。例如,id_in=3,5,等同于where id in (3,5)。表達式可以是列表、元組、字符串,也可以是filter()、exclude()和get()等方法返回的包含單個字段值的查詢集(QuerySet)gt大于。例如,id_gt=3等同于where id 3gte大于等于。例如,id_gte=3等同于where id =3lt小于。例如,id_lt=3,等同于where id

25、 3lte小于等于。例如,id_lte=3等同于where id d=faqsdata.objects.get(id=3)#獲得要修改的數據行 print(d.id,d.question,d.answer)#輸出數據3 test bbb d.question=如何更新數據#給屬性賦值 d.save()#將更好后的數據存入數據庫 print(d.id,d.question,d.answer) #輸出更新后的數據3 如何更新數據 bbb可通過對篩選結果執行update()方法來更新單個或多個數據行示例代碼如下。 ds=faqsdata.objects.filter(id=3) #獲得符合條件的數據

26、行 ds.update(answer=對象賦值或update()方法)#更新查詢集中所有對象的answer字段1update()方法命令返回更新后的數據行數量。調用模型的objects.update()方法可更新表中的全部數據行示例代碼如下。faqsdata.objects.update(question=Django常見問題)#更新表中的全部數據行34.2.6刪除數據delete()方法用于刪除數據行示例代碼如下。 faqsdata.objects.get(id=3).delete()(1, faqs.faqsdata: 1)delete()方法返回一個元組,元組的第1個值為已刪除的對象個數

27、(即刪除的數據行數),元組的第2個值是一個字典,它包含了對象類型和刪除的對象個數。例如,“faqs.faqsdata: 1”表示刪除了一個類型為faqs.faqsdata的對象。可用delete()方法刪除表中的全部數據示例代碼如下。 faqsdata.objects.all().delete()(3, faqs.faqsdata: 3)4.2.7查詢集操作1計算長度可使用len()和count()方法獲取查詢集長度,查詢集長度是查詢集從數據庫返回的數據行數示例代碼如下。 ds=faqsdata.objects.all() ds.count()3 len(ds)32迭代操作all()、orde

28、r_by()、exclude()和filter()方法返回的查詢集封裝的是模型對象values()方法返回的查詢集封裝的是字典對象values_list()返回的查詢集封裝的是元組。不管查詢集封裝的是哪種類型的對象,均可執行迭代操作。可使用for in循環對查詢集執行迭代操作,示例代碼如下。 ds=faqsdata.objects.all() for a in ds:#執行迭代. print(a.id,a.question)還可使用iterator()方法返回查詢集的迭代器,然后使用next()方法執行迭代示例代碼如下。 ds=faqsdata.objects.all() it=ds.iter

29、ator() #獲取迭代器 while True:. try: . a=next(it) #用迭代方法獲取對象. print(a.id,a.question) . except StopIteration as e: . print(迭代結束) next()方法在迭代結束時,會觸發StopIteration異常。3切片操作查詢集支持切片操作,示例代碼如下。 ds=faqsdata.objects.all():2#返回前2條數據 for a in ds:. print(a.id,a.question,a.answer).3 test bbb4 test3 test34布爾運算查詢集可作為邏輯值用

30、于布爾運算,如用于bool()、if、and、or等。作為邏輯值使用時,查詢集中不為空時,其值為True,否則為False示例代碼如下。 ds=faqsdata.objects.filter(answer_contains=test) if ds:. print(存在包含test的answer字段). else:. print(不存在包含test的answer字段)在測試查詢集是否包含查詢結果時,用exists()方法的效率更高,示例代碼如下。 if ds.exists():. print(有符合條件的數據). else:. print(沒有符合條件的數據)5&和|運算查詢集支持&(與)和|(

31、或)運算。執行&或|運算時,兩個查詢集必須使用相同的模型,Django會將兩個查詢集的過濾條件合并,等價于SQL中的“where and ”和“where or ”。&運算例如,下面的命令返回question和answer字段均包含“test”的數據行。ds=faqsdata.objects.filter(question_contains=test) & faqsdata.objects.filter(answer_contains =test)等價于:ds=faqsdata.objects.filter(question_contains=test, answer_contains=tes

32、t)等價于SQL中的“SELECT * FROM faqs_faqsdata WHERE question like %test% and answer like %test%”。還可以使用Q對象來創建類似的&或|運算,示例代碼如下。 from django.db.models import Q ds=scores.objects.filter(Q(sx_gt=60) & Q(xm_startswith=李)等價于:ds=scores.objects.filter(sx_gt=60, xm_startswith=李)ds=scores.objects.filter(sx_gt=60) & sc

33、ores.objects.filter(xm_startswith=李)|運算例如,下面的命令返回yw或sx字段大于90的數據行。 ds=scores.objects.filter(Q(sx_gt=90) | Q(yw_gt=90)等價于:ds=scores.objects.filter(sx_gt=90) | scores.objects.filter(yw_gt=90)4.3 索引索引是數據庫表中對一列或多列的值進行排序的一種結構。默認情況下,Django為模型的主鍵和外鍵創建索引。通常,索引可以大大提高表的查詢、更新和刪除速度,但會降低表的插入速度本節主要內容使用字段選項創建索引在Met

34、a子類中定義索引4.3.1使用字段選項創建索引與索引有關的字段選項如下。db_index:為True時,為字段創建索引。primary_key:為True時,字段為模型的主鍵,為字段創建索引。unique:為True時,為字段創建唯一索引。unique_for_date、unique_for_month和unique_for_year等選項與unique類似。下面的代碼使用字段選項為模型創建索引。#chapter4chapter4faqsmodels.pyfrom django.db import modelsclass test1(models.Model): field1=models.C

35、harField(max_length=200,db_index=True)#為字段創建普通索引 field2=models.CharField(max_length=200,unique=True)#為字段創建唯一索引4.3.2在Meta子類中定義索引模型的Meta子類用于為模型定義描述相關屬性的元數據。Meta類的indexes選項用于為模型定義索引。例如,下面的代碼為模型創建索引。#chapter4chapter4faqsmodels.pyfrom django.db import modelsclass test2(models.Model): field1=models.CharFi

36、eld(max_length=200) field2=models.CharField(max_length=200) class Meta: indexes = models.Index(fields=field1,name=idx_field1) #定義索引參數fields設置用于創建索引的字段,參數name設置索引名稱。如果需要創建基于多個字段的索引,可在參數fields中包含多個字段名稱,例如,fields=field1, field2。在模型的Meta子類中,還可使用unique_together屬性創建組合唯一索引。組合唯一索引要求多個字段的組合值在表中唯一。為模型創建組合唯一索引

37、的代碼如下。#chapter4chapter4faqsmodels.pyfrom django.db import modelsclass test3(models.Model): field1=models.CharField(max_length=200) field2=models.CharField(max_length=200) class Meta: unique_together=(field1,field2) #創建組合唯一索引4.4 特殊查詢表達式Django提供一些內置表達式來完成特殊操作,如F()表達式、數據庫函數表達式、Subquery()表達式、Exists()子查詢

38、以及原始SQL表達式等。本節主要內容準備實例數據F()表達式數據庫函數表達式Subquery()表達式聚合函數原始SQL表達式4.4.1準備實例數據首先需要在models.py文件中添加模型定義然后將模型遷移到數據庫最后將scores.csv文件中的數據導入數據表。具體操作步驟:演示4.4.2F()表達式F()表達式用于引用數據庫中的字段值,并使用它們直接在數據庫中完成操作,而不會將字段值從數據庫讀取到Python內存中。例如,要將faqs_scores表中kh為“10110103”的yw字段增加10,傳統方法如下。 from faqs.models import scores d=score

39、s.objects.get(kh=10110103) d.yw=d.yw+10#獲取yw字段值,加上10后賦值給字段 d.save()#將更改存入數據庫傳統方法在增加字段值時,需要先將字段值從數據庫讀取到Python內存中,修改后再調用save()方法將更改后的數據寫回數據庫。使用F()表達式來完成數據修改的命令如下。 from faqs.models import scores from django.db.models import F d=scores.objects.get(kh=10110103) d.yw=F(yw)+10#更新字段 d.save()#將更改存入數據庫使用F()表達

40、式修改數據后,要獲得更新后的值,需要重新加載對象示例代碼如下。 d=scores.objects.get(kh=10110103) 或者: d.refresh_from_db()F()表達式還可在過濾器中使用。例如,下面的命令獲得yw和sx字段值相等的數據行。 ds=scores.objects.filter(yw=F(sx) for a in ds:. print(a.id,a.kh,a.xm,a.yw,a.sx).12 10130528 向軍 95 9548 10330509 周子棚 70 7059 10351105 封舒寧 88 884.4.3數據庫函數表達式在查詢表達式中可使用數據庫函

41、數,如Left、Length、Right等示例代碼如下。 from django.db.models.functions import Left ds=scores.objects.annotate(first_name=Left(xm,1) ds0.first_name,ds0.xm(吳, 吳忱)4.4.4Subquery()表達式Subquery()表達式用于創建SQL子查詢。例如,下面的代碼輸出yw字段中值排前3名的數據。 from django.db.models import Avg,Subquery ywavg=scores.objects.aggregate(Avg(yw) su

42、bq=scores.objects.filter(yw_gt=ywavgyw_avg).order_by(-yw) top3=scores.objects.filter(id_in=Subquery(subq.values(id):3) for a in top3:. print(a.xm,a.yw).張慧賢 118向軍 95杜洋 1074.4.5聚合函數聚合函數用于執行匯總計算,如計算最大值、最小值、平均值等。Django提供的聚合函數如下:Avg:求平均值。Count:求數量。Max:求最大值。Min:求平均值。StdDev:求標準差。Sum:求和。Variance:求差額。聚合函數通常作

43、為aggregate()方法的查詢表達式使用。例如,下面的命令返回yw字段的平均值、最大值和最小值。 from faqs.models import scores from django.db.models import Avg,Max,Min scores.objects.aggregate(Avg(yw),Max(yw),Min(yw)yw_avg: 48.693548387096776, yw_max: 118, yw_min: 0默認情況下,返回的匯總值字段名為“匯總字段名_小寫的聚合函數名”。可以在查詢表達式中指定返回的字段名示例代碼如下。scores.objects.aggrega

44、te(ywavg=Avg(yw),ywmax=Max(yw),ywmin=Min(yw)ywavg: 48.693548387096776, ywmax: 118, ywmin: 0可結合使用values()和annotate()方法,實現分類匯總,即實現SQL中group by的功能。例如,按bj分類計算yw和sx字段平均值。 ds=scores.objects.values(bj).annotate(Avg(yw),Avg(sx) for a in ds:. print(abj,ayw_avg,asx_avg).class1 48.0 78.29411764705883class2 44.

45、333333333333336 73.52380952380952class3 52.166666666666664 70.20833333333333在分類匯總時,應注意values()方法總是在annotate()方法之前。若values()方法放在annotate()方法之后,則返回包含指定列字典對象的查詢集示例代碼如下。 ds=scores.objects.annotate(Avg(yw),Avg(sx).values(bj) print(ds0,ds1,ds2)bj: class1 bj: class1 bj: class14.4.6原始SQL表達式原始SQL表達式可完成一些比較復雜

46、的查詢。django.db.models. expressions模塊中的RawSQL類用于構造原始SQL表達式。例如,下面的命令計算scores表中yw字段值不小于90的數量,并按yw字段值從高到低輸出前4名學生的信息。from django.db.models.expressions import RawSQLds=scores.objects.all().annotate(ywgt90=RawSQL(select count(*) from faqs_scores where yw=%s, (90,) for a in ds.order_by(-yw):4:. print(a.xm,a.

47、yw,a.ywgt90).張慧賢 118 3杜洋 107 3向軍 95 3奉蕓龍 89 34.5執行原始SQL查詢Django提供了兩種執行原始SQL查詢的方法:用模型管理器的raw()方法執行原始SQL查詢并返回模型實例不使用模型直接執行原始SQL。建議使用模型完成數據庫訪問,直接使用原始SQL存在SQL注入風險。本節主要內容用raw()方法執行原始SQL直接執行原始SQL4.5.1用raw()方法執行原始SQLraw()方法通常用于執行SQL中的select查詢,該方法的返回結果是一個RawQuerySet對象實例。RawQuerySet對象可用于迭代、計算長度、索引等操作。1執行簡單查詢

48、 from faqs.models import scores ds=scores.objects.raw(select * from faqs_scores where yw90 and sx90) ds#查看對象類型90 and sx90 for a in ds:#迭代RawQuerySet. print(a.id,a.kh,a.yw,a.sx)#訪問對象數據,此時從數據庫檢索數據.12 10130528 95 95 len(ds)#計算長度1 print(ds0.id,ds0.xm)#索引RawQuerySet12 向軍raw()方法執行SQL命令時,會延遲執行數據庫操作,只有在訪問對象

49、數據時,才會從數據庫檢索數據。2為查詢提供參數可通過raw()方法的第2個參數為查詢提供參數示例代碼如下。 ds=scores.objects.raw(select * from faqs_scores where kh=%s,10110103) print(ds0.id,ds0.xm)1 吳忱在raw()方法的SQL查詢字符串中,用%s作為參數占位符,對應的參數應放在列表中。當參數是字符串時,不需要在查詢字符串中為參數占位符添加引號,Django會自動處理參數中的字符串。3添加計算字段可以在SQL查詢字符串中使用表達式添加計算字段,模型對象會將計算字段作為注釋字段處理。例如,下面的命令返回y

50、w和sx字段值的和。 ds=scores.objects.raw(select id,yw,sx,yw+sx as total from faqs_scores limit 3) for a in ds:. print(a.id,a.xm,a.yw,a.sx,a.total).1 吳忱 85 76 1612 楊九蓮 33 99 1323 安蕓蕓 39 84 123注意,盡管在查詢字符串中指定了輸出字段,但raw()方法仍然會從數據庫返回模型的所有字段,查詢結果中出現的模型未定義的字段將作為注釋字段處理,類似于annotate()方法。4執行insert、update和delete等SQL命令r

51、aw()方法也可以執行SQL中的insert、update和delete命令示例代碼如下。 from faqs.models import faqsdata d=faqsdata.objects.raw(update faqs_faqsdata set answer=%s where id=3,raw修改 )d.query._execute_query()#立即執行查詢命令 d=faqsdata.objects.raw(insert into faqs_faqsdata(question,answer) values(測試1,測試1答案) ) d.query._execute_query()

52、d=faqsdata.objects.raw(delete from faqs_faqsdata where id=6 ) n=d.query._execute_query()調用raw()方法時,參數中的SQL insert、update和delete等命令不會立即執行查詢,調用RawQuerySet對象的query屬性的_execute_query()方法時才會執行查詢,使數據庫操作生效4.5.2直接執行原始SQLDjango提供了不使用模型訪問數據庫的方法,基本步驟如下。(1)調用django.db.connection.cursor()方法獲得一個游標對象。django.db.conn

53、ection對象代表默認數據庫連接。(2)調用游標對象的execute(sql, params)方法執行SQL命令。(3)調用游標對象的fetchone()或fetchall()方法返回數據。1執行SQL select命令下面的命令輸出faqs_faqsdata表中的數據。 cursor=connection.cursor() cursor.execute(select * from faqs_faqsdata) for a in cursor.fetchall():. print(a0,a1,a2).3 bbb test4 test3 test35 aaa test8fetchall()方法

54、返回包含全部數據的列表,數據庫中的每行數據對應一個元組,示例代碼如下。 a=cursor.execute(select * from faqs_faqsdata) a.fetchall()(3, bbb, test), (4, test3, test3), (5, aaa, test8)fetchone()方法返回當前數據行,調用一次方法會使下一個數據行成為當前行,示例代碼如下。 a=cursor.execute(select * from faqs_faqsdata) a.fetchone()(3, bbb, test) a.fetchone()(4, test3, test3) a.fet

55、chone()(5, aaa, test8)可以在查詢字符串中用參數占位符指定參數。例如,下面的命令返回answer字段不包含字符串“test”的數據。 a=cursor.execute(select * from faqs_faqsdata where answer not like %s,%test%) a.fetchall()(3, bbb, test), (5, aaa, test8)2執行insert、update和delete等SQL命令下面的命令為faqs_faqsdata表添加一條記錄,并進行修改,最后將其刪除。 a=cursor.execute(insert into faq

56、s_faqsdata(question,answer) values(如何獲取全部數據,fetchall()#添加數據 cursor.execute(select * from faqs_faqsdata).fetchall()#查看全部數據(3, bbb, test), (4, test3, test3), (5, aaa, test8), (7, fetchall(), 如何獲取全部數據) a=cursor.execute(update faqs_faqsdata set question=測試 where id=7)#修改數據 cursor.execute(select * from f

57、aqs_faqsdata where id=7).fetchall() #查看修改后的數據(7, fetchall(), 測試) a=cursor.execute(delete from faqs_faqsdata where id=7) #刪除數據 cursor.execute(select * from faqs_faqsdata ).fetchall()(3, bbb, test), (4, test3, test3), (5, aaa, test8)3關閉游標調用close()方法可關閉游標,釋放被占用的系統資源示例代碼如下。 cursor.close() #關閉游標4.6 關系在處理

58、多個數據表時,會使用表之間的關聯關系。Django支持3種常見關系:多對一(或稱“一對多”)多對多一對一。本節主要內容多對一關系多對多關系使用中間模型一對一關系4.6.1多對一關系多對一關系指關聯的兩個表中,“多”方表中有多條記錄與“一”方表中的一條記錄關聯。例如,學生和班級之間的關系是多對一關系,多個學生屬于一個班級。1定義多對一關系多對一關系使用models.ForeignKey字段進行定義示例代碼如下。class banj(models.Model): #班級模型,關系的“一”方 mc=models.CharField(max_length=8) #班級名稱 def _str_(self

59、): return self.mc class xues(models.Model): #學生模型,關系的“多”方 xm=models.CharField(max_length=8) #學生姓名 bj=models.ForeignKey(banj,on_delete=models.CASCADE)#外鍵,關聯班級 def _str_(self): return %s %s % (self.xm,self.xh)學生模型xues和班級模型banj構成多對一關系。默認情況下,Django按id字段建立兩個模型的關聯關系。也可在定義ForeignKey字段時,用to_field參數指定關聯字段。Fo

60、reignKey字段的on_delete參數用于設置在刪除多對一關系中“一”方對象時,如何處理“多”方中的關聯對象。各參數值的含義如下。CASCADE:級聯刪除“多”方的關聯對象。PROTECT:保護模式,當“多”方存在關聯對象時,不允許刪除“一”方對象,此時會觸發ProtectedError異常。SET_NULL:允許刪除“一”方對象,同時將ForeignKey字段設置為null,這要求在定義時將ForeignKey字段的null選項設置為True。SET_DEFAULT:允許刪除“一”方對象,同時將ForeignKey字段設置為默認值,這要求在定義時為ForeignKey字段設置默認值 。

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論