雙十一光顧著買東西都沒怎麼寫文章,現在筆記裡還有十幾篇半成品文章沒寫完…
今天來分享一下 Django 專案切換資料庫和遷移資料的方案,網路上找到的文章方法不一,且使用中容易遇到各類報錯,本文根據 Django 官方檔案和工作中的經驗,穩定可靠,在部落格中長期更新~
如果你遇到同樣的問題,閱讀本文應該能得到比較好的解決方案。
Django 預設使用 SQLite 資料庫方便開發,同時其 ORM 支援多種資料庫,只要安裝對應的驅動就行。
切換資料庫一般是將開發環境的 SQLite 切換到 MySQL (MariaDB) 或 PostgreSql ,本文只測試了從 SQLite 到 MySQL / PostgreSQL,同理,其他切換路徑也是可以的。
資料庫的表結構沒啥問題,使用 Django 的 migrate 功能就行了
關鍵在於資料遷移,可以使用 Navicat 之類的資料庫工具進行資料同步,但往往會因為表之間的約束關係導致同步失敗(要求按特定順序匯入資料)。
所以最好的方法是使用 Django 的 dumpdata
功能,將資料庫匯出為 json 或 xml 檔案,然後切換資料庫再匯入。
步驟如下:
python manage.py dumpdata -o db.json
settings.py
裡切換到新的資料庫python manage.py migrate
python manage.py loaddata db.json
搞定~
附上幾種資料庫設定,方便使用
db_config = {
'sqlite': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
'OPTIONS': {
'timeout': 20,
}
},
'pgsql': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': '資料庫名稱',
'USER': '使用者名稱',
'PASSWORD': '密碼',
'HOST': '資料庫伺服器地址',
'PORT': 5432,
},
'mysql': {
'ENGINE': 'django.db.backends.mysql',
'NAME': '資料庫名稱',
'USER': '使用者名稱',
'PASSWORD': '密碼',
'HOST': '資料庫伺服器地址',
'PORT': 3306,
}
}
# 這裡可以方便切換不同資料庫
DATABASES = {'default': db_config['pgsql']}
其中:
mysqlclient
包psycopg2
包然後,事情往往沒有這麼簡單和順利,匯出匯入的過程中可能會遇到一些問題,請繼續看~
報錯資訊
CommandError: Unable to serialize database: 'gbk' codec can't encode character '\u30fb' in position 4: illegal multibyte sequence
原因跟編碼有關
使用 Python 的 UTF-8 模式匯出資料就沒問題
用這個命令匯出檔案
(不匯出 auth.permission
和 contenttypes
,這倆在 migrate
時會自動生成,這樣避免了匯入原有資料時衝突)
python -Xutf8 manage.py dumpdata --exclude auth.permission --exclude contenttypes > db.json
或者
python -Xutf8 manage.py dumpdata -o db.json
django.db.utils.IntegrityError: Problem installing fixture 'db.json' Could not load contenttypes.ContentType(pk=15): (1062, "Duplicate entry 'xxx' for key 'django_content_type.django_content_type_app_label_model_76bd3d3b_uniq'")
加上這倆引數
--natural-primary
: Omits the primary key in the serialized data of this object since it can be calculated during deserialization.--natural-foreign
: Uses the natural_key() model method to serialize any foreign key and many-to-many relationship to objects of the type that defines the method.作用是匯出的時候去除一些約束,匯入時會自動處理,減少匯入時因為表之間約束關係的問題
python3 manage.py dumpdata --natural-primary --natural-foreign -o db.json
content_type
資料另一種思路,把 migrate
過程產生的初始化資料刪了,避免匯入時和原有資料衝突
先進入 python shell
python3 manage.py shell
輸入以下Python程式碼執行
from django.contrib.contenttypes.models import ContentType
ContentType.objects.all().delete()
UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xff in position 0: invalid start byte in Django
在匯入命令前面加上 -Xutf8
引數
python -Xutf8 manage.py loaddata db.json
能用,但不推薦,實在沒辦法再來試這個方法
修改檔案
lib\site-packages\django\core\serializers\json.py
在 Deserializer
方法中找到這行程式碼
stream_or_string = stream_or_string.decode()
改成這樣
stream_or_string = stream_or_string.decode('UTF-16')
再進行匯入操作