Django Web應用開發實戰第七章

一、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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章