通過db_table和db_column自定義數據表名和字段名
假如你的數據庫里已經有了一張數據表,且該表包含多個字段,你希望通過Django直接訪問該數據表的各個字段而不是重新建立新表,你這時可以通過db_table指定數據表名,還可以通過db_column指定希望訪問的字段名。
在我們創建一個模型時,Django的ORM會根據應用名(app name), 模型名(model name)和字段名(field name)自動在數據庫中創建數據表。比如我們有一個Blog的應用,里面有Article模型, 其中Article模型有title這個字段,那么Django默認會創建一個名為blog_article的數據表,其中有title這個字段。假如我們希望把表名改為article,標題改為article_title,以便與已經存在的數據表或字段建立映射關系,我們可以按如下代碼操作。
class Article(models.Model): """文章模型""" # 通過db_column自定義數據表中字段名 title = models.CharField('標題', max_length=200, db_column='article_title') slug = models.SlugField('slug', max_length=60, blank=True) def __str__(self): return self.title class Meta: db_table = 'article' # 通過db_table自定義數據表名
通過db_index和Meta index選項給數據表字段建立索引
使用索引可快速訪問數據庫表中的特定信息。數據庫索引好比是一本書前面的目錄,沒有索引目錄的話,你訪問書中某個頁面需要從第1頁遍歷到最后一頁,如果有目錄,你可以快速地根據目錄查找到所需要的頁面。Django項目中如果你需要頻繁地對數據表中的某些字段(如title)使用filter(), exclude()和order_by()方法進行查詢,我們強烈建議你對這些字段建議索引(index), 提升查詢效率。
要對模型中的某個字段建立數據庫索引,你可以使用db_index選項,也可以使用Meta選項建立索引。使用Meta選項的好處是你可以一次性對多個字段建立索引,還可以對多個字段建立組合索引。
方法一: 使用db_index選項 class Article(models.Model): """文章模型""" # 使用db_index=True對title建立索引 title = models.CharField('標題', max_length=200, db_index=True)
方法二: 使用Meta選項 class Article(models.Model): """文章模型""" title = models.CharField('標題', max_length=200,) class Meta: indexes = [ models.Index(fields=['title']), ]
Django主從數據庫配置
當你剛剛開始建立一個網站時,可能每天只有數十到上百人訪問。這時你只有一個數據庫,所有APP的數據表也都放一起的,一台普通的服務器能夠應付, 也便於維護。但是當訪問量上來后,你會發現一台服務器和一個數據庫會根本應付不了這個壓力。這時你可能希望實現數據庫的主從配置,讀寫分離,把各個數據庫放在不同的服務器上,有的專門負責寫入,有的專門負責讀取,這時你就要學會使用Django同時連接多個數據庫,並自定義讀寫操作。
第一步 修改項目的 settings 配置
在 settings.py 中配置需要連接的多個數據庫名稱和登錄信息。在下例中我們自定義了3個數據庫,1個主數據庫(primary), 2個從數據庫(replica)。
#project/settings.py DATABASES = { 'default': {}, 'primary': { 'NAME': 'primary', 'ENGINE': 'django.db.backends.mysql', 'HOST': 'xxxx', 'PORT': 'xxxx', 'USER': 'mysql_user', 'PASSWORD': 'spam', }, 'replica1': { 'NAME': 'replica1', 'ENGINE': 'django.db.backends.mysql', 'HOST': 'xxxx', 'PORT': 'xxxx', 'USER': 'mysql_user', 'PASSWORD': 'eggs', }, 'replica2': { 'NAME': 'replica2', 'ENGINE': 'django.db.backends.mysql', 'HOST': 'xxxx', 'PORT': 'xxxx', 'USER': 'mysql_user', 'PASSWORD': 'bacon', }, }
我們還需要在 settings.py
添加我們手動編寫的數據庫路由Router。路由的作用是為數據庫的讀寫制定規則。
DATABASE_ROUTERS = ['Project.database_router.PrimaryReplicaRouter']
注意: 主從數據庫的同步是通過MySQL配置實現的,而不是Django實現的。Django只負責多個數據庫的訪問,不負責各個數據庫的同步工作。如果你定義了多個路由,請一定注意路由的執行順序。
第二步 自定義數據庫路由Router
在Django項目的根目錄下創建 database_router.py 文件, 添加如下代碼,自定義數據庫路由。該路由規定了讀取數據時將隨機從replica1和replica2數據庫中讀取,而寫入數據總是寫入主數據庫primary。該路由還允許三個數據庫中的字段建立聯系。
class PrimaryReplicaRouter(object): def db_for_read(self, model, **hints): """ Reads go to a randomly-chosen replica. """ return random.choice(['replica1', 'replica2']) def db_for_write(self, model, **hints): """ Writes always go to primary. """ return 'primary' def allow_relation(self, obj1, obj2, **hints): """ Relations between objects are allowed if both objects are in the primary/replica pool. """ db_list = ('primary', 'replica1', 'replica2') if obj1._state.db in db_list and obj2._state.db in db_list: return True return None def allow_migrate(self, db, app_label, model_name=None, **hints): """ All models end up in this pool. """ return True
一個數據庫路由是一個類,這個類最多有四個方法:
db_for_read(model, **hints)
建議 model 對象進行讀操作時使用的數據庫。如果一個數據庫操作可以提供對選擇數據庫有用的附加信息,那么可以通過 hints 字典提供。如果沒有建議則返回 None 。
db_for_write(model, **hints)
建議 model 對象進行寫操作時使用的數據庫。如果一個數據庫操作可以提供對選擇數據庫有用的附加信息,那么可以通過 hints 字典提供。如果沒有建議則返回 None 。
allow_relation(obj1, obj2, **hints)
當 obj1 和 obj2 之間允許有關系時返回 True ,不允許時返回 False ,或者沒有意見時返回 None 。這是一個純粹的驗證操作,用於外鍵和多對多操作中,兩個對象的關系是否被允許。
allow_migrate(db, app_label, model_name)
決定 model 是否可以和 db 為別名的數據庫同步。如果可以返回True , 如果不可以返回 False ,或者沒有意見時返回 None 。
Django項目按APP分庫
在大型web項目中,我們常常會創建多個app來處理不同的業務,如果希望實現app之間的數據庫分離,比如app01走數據庫db1,app02走數據庫db2,而不是實現讀寫分離。我們可以定義如下所示的數據庫路由, 然后將其加入settings.py 。
class AppDBRouter: def db_for_read(self, model, **hints): if model._meta.app_label == 'app01': return 'db1' if model._meta.app_label == 'app02': return 'db2' def db_for_write(self, model, **hints): if model._meta.app_label == 'app01': return 'db1' if model._meta.app_label == 'app02': return 'db2'
由於manage.py一次只能創建一個數據庫,我們可以使用--database選項來依次創建我們需要的數據庫。例如:
將app01下models中的表創建到db01的數據庫”db1”中
python manage.py migrate --database=db1
將app02下models中的表創建到db02的數據庫”db2”中
python manage.py migrate --database=db2
在使用多數據庫時,我們可以使用using方法來手動選擇需要讀寫的數據庫,如下所示:
Aricle.objects.using('db1').all() article_object.save(using='db2')
Django中使用多數據庫注意事項:
django 目前不為跨多個數據庫的外鍵關系(ForeinKey)或多對多關系提供任何支持。模型定義的任何外鍵和多對多關系字段都必須存在一個數據庫內。