一、ORM框架
Django對各種數據庫提供了很好的支持,包括PostgreSQL、MySQL、SQLite和Oracle,且爲這些數據庫提供了統一API方法,這些API統稱爲ORM框架。
通過Django內置的ORM框架可以實現數據庫連接和讀寫操作。
二、模型定義與數據遷移
ORM框架是一種程序技術,用於實現 面向對象編程語言中不同類型系統的數據之間的轉換,從效果上說,它創建了一個可在編程語言中使用的“虛擬對象數據庫”,通過對虛擬對象數據庫的操作,實現對目標數據庫的操作,虛擬對象數據庫與目標數據庫是相互對應的。在Django中虛擬對象數據庫也稱爲模型。模型字段如下:
- AutoField: 自增長類型,數據表的字段類型爲整數,長度爲11位
- BigAutoField: 自增長類型,數據表的字段類型爲bigint,長度爲20位
- CharField: 字符類型
- BooleanField: 布爾類型
- CommonSeparateIntegerField: 用逗號分割的整數類型
- DateField: 日期(Date)類型
- DatetimeField: 日期時間(Datetime)類型
- Decimal: 十進制小數類型
- EmailField: 字符類型,存儲郵箱格式的字符串
- FloatField: 浮點數類型,數據表的字段類型變成Double類型
- IntegerField: 整數類型,數據表的字段類型爲11位的整數
- BigIntegerField: 長整數類型
- IPAddressField: 字符類型,存儲Ipv4地址的字符串
- GenericIPAddressField: 字符類型,存儲Ipv4和Ipv6地址的字符串
- NullBooleanField: 允許爲空的布爾類型
- PositiveIntegerField: 正整數的整數類型
- PositiveSmallIntegerField: 小正整數類型,取值範圍0~32767
- SlugField: 字符類型,包含字母、數字、下劃線和連字符的字符串
- TextField: 長文本類型
- TimeField: 時間類型,顯示時分秒HH:MM[:ss[.uuuuuuu]]
- URLField: 字符類型,存儲路由格式的字符串
- BinaryField: 二進制數據類型
- FileField: 字符類型,存儲文件路徑的字符串
- ImageField: 字符類型,存儲圖片路徑的字符串
- FilePathField: 字符類型,從特定的文件目錄選擇某個文件
允許設置的參數
源碼Field(django/db/models/fields/init.py)
- verbose_name: 默認None,在Admin站點管理設置字符的顯示名稱
- primary_key: 默認爲False,若爲True,則將字段設置成主鍵
- max_length: 默認爲None,設置字段的最大長度
- unique: 默認爲False,若爲True,則設置字段的唯一屬性
- blank: 默認爲False, 若爲True,則設置字段允許爲空值,數據庫將存儲空字符串
- null: 默認爲False,若爲True,則字段允許爲空值,數據庫表現爲NULL
- db_index: 默認爲False,若爲True,則以此字段來創建數據庫索引
- default: 默認爲NOT_PROVIDEDD對象,設置字段的默認值
- editable: 默認爲True,允許字段可編輯,用於設置Admin的新增數據的字段
- serialize: 默認爲True,允許字段序列化,可將數據轉化爲JSON格式
- unique_for_date: 默認爲None,設置日期字段的唯一性
- unique_for_month: 默認爲None,設置月份字段的唯一性
- unique_for_year: 默認爲None,設置年份字段的唯一性
- choices: 默認空列表,設置字段的可選值
- help_text: 默認爲空字符串,用於設置表單的提示信息
- db_column: 默認爲None,設置數據表的列名稱,若不設置,則字段名作爲列名
- db_tablespace: 默認爲None,如果字段已創建索引,那麼數據庫的表空間名稱將作爲該字段的索引名稱。注意:部分數據庫不支持表空間
- auto_created: 默認爲False,若爲True,則自動創建字段,用於一對一的關係模型
- validators: 默認爲空列表,設置字段內容的驗證函數
- error_message: 默認爲None,設置錯誤提示
- 以上參數適用於所有字段
- 以下適用於Meta
- abstract: 若設置爲True,則該模型爲抽象模型,不會在數據庫裏創建數據表
- app_label:屬性值爲字符串,將模型設置爲指定的項目應用,比如將index的models.py定義的模型A指定到其他的APP裏
- db_table: 屬性值爲字符串,設置模型所使用的數據庫的表名
- db_tablespace: 屬性值爲字符串,設置模型所使用的數據庫的表名
- get_lastest_by: 屬性值爲字符串或列表,設置模型數據的排序方式
- managed: 默認爲True,支持Django命令執行數據遷移;若爲False,則不支持數據遷移功能
- order_with_respect_to: 屬性值爲字符串,用於多對多的模型關係,指向某個關係模型的名稱,並且模型名稱必須爲英文小寫。若A模型對B模型一對多,兩個模型關聯後,當查詢模型A的某條數據時,可使用get_b_order()和set_b_order()來獲取B的關聯數據;可使用get_next_in_order()和get_previous_in_order()獲取當前數據的上一條和下一條數據
- ordering: 屬性值爲列表,將模型數據以某個字段進行排序
- permissions: 屬性值爲元組,設置模型的訪問權限,默認設置添加、修改和刪除的權限
- proxy:若設置爲True,則爲模型創建代理模型,即爲模塊A克隆一個相同的模型B
- required_db_features:屬性值爲列表,聲明模型依賴的數據庫功能,如['gis_enabled'],表示模型依賴GIS功能
- required_db_vendor: 屬性值爲列表,聲明模型依賴的數據庫,默認支持SQLite、PostgreSQL、MySQL和Oracle
- select_on_save: 數據新增修改算法,通常無需設置,默認爲False
- indexes: 屬性值爲列表,定義數據庫表的索引列表
- verbos_name: 屬性值爲字符串,設置模型直觀可讀的名稱並以複數形式表示
- verbos_name_plural: 與verbos_name相同,以單數形式表示
- label: 只讀屬性,屬性值爲app_label.object_name
- label_lower: 與label相同,但其值爲字母小寫
導數據
# 導出項目所有數據表 python manage.py dumpdata > data.json # 導出某個項目名稱所有模型 python manage.py dumpdata index > data.json # 導出某個項目某個模型名稱 python manage.py dumpdata index.PersonInfo > data.json # 導入數據 python manage.py loaddata data.json
三、數據表關係
# OneToOneField、ForeignKey、ManyToManyField # 參數 - to: 必選參數,關聯的模型名稱 - on_delete: 必選參數,設置數據刪除模式,刪除模型包括:CASCADE/PROTECT/SET_NULL/SET_DEFAULT/SET/DO_NOTHING - limit_choices_to: 設置外鍵的下拉選項,用於模型與表單和Admin後臺系統 - related_name: 用於模型之間的關聯查詢,如反向查詢 - related_query_name: 設置模型的查詢名稱,用於filter或get查詢,若設置參數related_name則以該參數爲默認值,若沒有設置,則以模型名稱的小寫爲默認值 - to_field: 設置外鍵與其他模型字段的關聯性,默認關聯主鍵,若要關聯其他字段,則該字段必須具有唯一性 - db_constraint: 在數據庫裏是否創建外鍵約束,默認爲true - swappable: 設置關聯模型的替換功能,默認爲true,比如模型A關聯模型B,想讓模型C繼承並替換B使得A與模型C之間關聯 - symmetrical: 僅限於ManyToManyField,設置多對多字段之間的對稱模式 - through: 僅限於ManyToManyField,設置自定義模型C,用於管理和創建模型A和B否多對多關係 - through_fields: 僅限於ManyToManyField,設置模型C的字段,確認模型C的哪些字段用於管理A和B否多對多關係 - db_table: 僅限於ManyToManyField,爲管理和存儲多對多關係的數據表設置表名稱
四、數據查詢
去重distinct
# 去重查詢,distinct無需設置參數,去重方式根據values設置的字段執行 # SQL: select * from index_vocation where job='123'; v = Vocation.objects.values('job').filter(job='123').distinct()
聚合查詢annotate、aggregate
# annotate類似sql裏面的group by # 如果不設置values,默認對主鍵進行group by分組 # SQL: select job, sum(id) as 'id__sum' from index_vocation group by job; v = Vocation.objects.annotate(Sum('id')) # aggregate是計算某個字段的值並返回計算結果 # SQL: select count(id) as 'id__count' from index_vocation v = Vocation.objects.aggregate(id_count=Count('id'))
結果集union、intersection、difference
# 每次查詢的字段必須一致 v1 = Vocation.objects.filter(payment__gt=9000) v2 = Vocation.objects.filter(payment__gt=5000) # 使用SQL UNION來組合兩個或多個查詢結果的並集 v1.union(v2) # 使用SQL INTERSECT來獲取兩個或多個查詢結果的交集 v1.intersection(v2) # 使用SQL EXCEPT來獲取兩個或多個查詢結果的差集 v2.difference(v2)
查詢條件get:查詢字段必須是主鍵或者唯一約束的字段,且查詢的數據必須存在,否則程序會拋異常
查詢條件filter:查詢字段沒有限制,只要該字段是數據表某一字即可。查詢結果以列表形式返回,查詢結果爲空就返回空列表
多表查詢select_related、prefetch_related
# select_related參數爲字符串格式(外鍵字段related_name), 使用left outer join方式查詢兩個數據表 # 查詢模型PersonInfo的name字段和模型Vocation的payment字段 p = PersonInfo.objects.select_related('personinfo').values('name', 'personinfo__payment') # select_related使用SQL的join實現的,對於多對多會增加數據查詢時間和內存佔用;prefetch_related更有優勢 # 查詢模型Program的某行數據 p = Program.objects.prefetch_related('performer').filter(name='123').first() # 根據外鍵字段proformer獲取當前數據的多對多或一對多關係 p.performer.all()
執行sql
# extra: 結果集修改器,一種提供額外查詢參數的機制 # 查詢job=123的數據 v = Vocation.objects.extra(where=['job=%s'], params=['123']) # 新增查詢字段seat, select_params爲selec的%s提供參數 v = Vocation.objects.extra(select={'seat': '%s'}, select_params=['seatInfo']) # raw v = Vocation.objects.raw('select * from index_vocation') v[0] # execute很容易受到sql注入攻擊 from django.db import connection cursor = connection.cursor() cursor.execute('select * from index_vocation') # 讀取第一行數據 cursor.fetchone() # 讀取所有數據 cursor.fetchall()
遷移到不同數據庫
# 在default數據庫中創建數據表 python manage.py migrate # 在db1中創建數據表 python manage.py migrate --database=db1
五、數據庫事務
事物是指作爲單個邏輯執行的一系列操作,這些操作具有原子性,即這些操作要麼完全執行,要麼完全不執行。 事物處理可以確保事務性單元內所有操作都成功完成,否則不會執行數據操作。 事物四大特性ACID: - 原子性(Atomicity):一個事物是一個不可分割的工作單位,事物中包括的操作要麼都做,要麼都不做。 - 一致性(Consistency):事物必須使數據庫從某個一致性狀態到另一個一致性狀態,一致性與原子性是密切相關的。 - 隔離性:一個事物的執行不能被其他事物干擾,即一個事物內部的操作及使用的數據對其他事物是隔離的,各個事物之間互不干擾。 - 持久性:也稱永久性(Permanence),指一個事物一旦提交,它對數據庫中數據的改變應該是永久性的,其他操作或故障不應該對其有任何影響。 # Django事物定義在django/db/transaction.py - atomic(): 在視圖函數或視圖類使用事物 - savepoint(): 開啓事物 - savepoint_rollback(): 回滾事物 - savepoint_save(): 提交事物
from django.shortcuts import render from .models import * from django.db import transaction from django.db.models import F @transaction.atomic def index(request): # 開啓事物保護 sid = transaction.savepoint() try: id = request.GET.get('id', '') if id: v = Vocation.objects.filter(id=id) v.update(payment=F('payment') + 1) print('Done') # 提交事物 # 如不設置,當程序執行完成後,會自動提交事物 # transaction.savepoint_commit(sid) else: # 全表的payment字段自減1 Vocation.objects.update(payment=F('payment') - 1) # 事物回滾,將全表payment字段自減1的操作撤回 transaction.savepoint_rollback(sid) except Expection as e: transaction.savepoint_rollback(sid) return render(request, 'index.html', local()) # 使用with模塊實現 with transaction.atmonic(): pass
六、發送郵件
# 郵件配置信息 EMAIL_USE_SSL = True # Django與郵件服務器的連接方式是否設置ssl模式 # 郵件服務器,如果是163,就改成smtp.163.com EMAIL_HOST = 'smtp.qq.com' # 設置服務器類型,qq郵箱分爲SMTP和POP3服務器 # 郵件服務器端口 EMAIL_PORT = 465 # 若使用SMTP服務器,則端口應爲465或587 # 發送郵件的賬號 EMAIL_HOST_USER = '[email protected]' # 賬號必須開啓POP3/SMTP服務 # SMTP服務密碼 EMAIL_HOST_PASSWORD = 'SFSDDSFSVGSF' # 授權碼 # 設置默認發送郵件的賬號 DEFAULT_FROM_EMAIL = EMAIL_HOST_USER