Django切換數(shù)據(jù)庫和遷移數(shù)據(jù)詳解
前言
今天來分享一下 Django 項(xiàng)目切換數(shù)據(jù)庫和遷移數(shù)據(jù)的方案,網(wǎng)絡(luò)上找到的文章方法不一,且使用中容易遇到各類報(bào)錯(cuò),本文根據(jù) Django 官方文檔和工作中的經(jīng)驗(yàn),穩(wěn)定可靠,在博客中長期更新~
如果你遇到同樣的問題,閱讀本文應(yīng)該能得到比較好的解決方案。
基本步驟
Django 默認(rèn)使用 SQLite 數(shù)據(jù)庫方便開發(fā),同時(shí)其 ORM 支持多種數(shù)據(jù)庫,只要安裝對應(yīng)的驅(qū)動(dòng)就行。
切換數(shù)據(jù)庫一般是將開發(fā)環(huán)境的 SQLite 切換到 MySQL (MariaDB) 或 PostgreSql ,本文只測試了從 SQLite 到 MySQL / PostgreSQL,同理,其他切換路徑也是可以的。
數(shù)據(jù)庫的表結(jié)構(gòu)沒啥問題,使用 Django 的 migrate 功能就行了
關(guān)鍵在于數(shù)據(jù)遷移,可以使用 Navicat 之類的數(shù)據(jù)庫工具進(jìn)行數(shù)據(jù)同步,但往往會(huì)因?yàn)楸碇g的約束關(guān)系導(dǎo)致同步失?。ㄒ蟀刺囟樞?qū)霐?shù)據(jù))。
所以最好的方法是使用 Django 的 dumpdata
功能,將數(shù)據(jù)庫導(dǎo)出為 json 或 xml 文件,然后切換數(shù)據(jù)庫再導(dǎo)入。
步驟如下:
- 導(dǎo)出原有數(shù)據(jù):
python manage.py dumpdata -o db.json
- 在目標(biāo)數(shù)據(jù)庫(MySQL / PostgreSql)里創(chuàng)建一個(gè)空的庫
- 在
settings.py
里切換到新的數(shù)據(jù)庫 - 建立新的數(shù)據(jù)庫表結(jié)構(gòu)
python manage.py migrate
- 導(dǎo)入原有數(shù)據(jù):
python manage.py loaddata db.json
搞定~
附上幾種數(shù)據(jù)庫配置,方便使用
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': '數(shù)據(jù)庫名稱', 'USER': '用戶名', 'PASSWORD': '密碼', 'HOST': '數(shù)據(jù)庫服務(wù)器地址', 'PORT': 5432, }, 'mysql': { 'ENGINE': 'django.db.backends.mysql', 'NAME': '數(shù)據(jù)庫名稱', 'USER': '用戶名', 'PASSWORD': '密碼', 'HOST': '數(shù)據(jù)庫服務(wù)器地址', 'PORT': 3306, } } # 這里可以方便切換不同數(shù)據(jù)庫 DATABASES = {'default': db_config['pgsql']}
其中:
- MySQL 需要安裝
mysqlclient
包 - PostgreSql 需要安裝
psycopg2
包
然后,事情往往沒有這么簡單和順利,導(dǎo)出導(dǎo)入的過程中可能會(huì)遇到一些問題,請繼續(xù)看~
導(dǎo)出報(bào)錯(cuò)
報(bào)錯(cuò)信息
CommandError: Unable to serialize database: 'gbk' codec can't encode character '\u30fb' in position 4: illegal multibyte sequence
原因跟編碼有關(guān)
解決方法
使用 Python 的 UTF-8 模式導(dǎo)出數(shù)據(jù)就沒問題
用這個(gè)命令導(dǎo)出文件
(不導(dǎo)出 auth.permission
和 contenttypes
,這倆在 migrate
時(shí)會(huì)自動(dòng)生成,這樣避免了導(dǎo)入原有數(shù)據(jù)時(shí)沖突)
python -Xutf8 manage.py dumpdata --exclude auth.permission --exclude contenttypes > db.json
或者
python -Xutf8 manage.py dumpdata -o db.json
導(dǎo)入過程出錯(cuò)解決
報(bào)錯(cuò)1: Duplicate entry
報(bào)錯(cuò)信息
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'")
解決方法一: 重新導(dǎo)出數(shù)據(jù)
加上這倆參數(shù)
--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.
作用是導(dǎo)出的時(shí)候去除一些約束,導(dǎo)入時(shí)會(huì)自動(dòng)處理,減少導(dǎo)入時(shí)因?yàn)楸碇g約束關(guān)系的問題
python3 manage.py dumpdata --natural-primary --natural-foreign -o db.json
解決方法二: 刪除 content_type
數(shù)據(jù)
另一種思路,把 migrate
過程產(chǎn)生的初始化數(shù)據(jù)刪了,避免導(dǎo)入時(shí)和原有數(shù)據(jù)沖突
先進(jìn)入 python shell
python3 manage.py shell
輸入以下Python代碼執(zhí)行
from django.contrib.contenttypes.models import ContentType ContentType.objects.all().delete()
報(bào)錯(cuò)2: 編碼錯(cuò)誤
報(bào)錯(cuò)信息
UnicodeDecodeError: ‘utf-8' codec can't decode byte 0xff in position 0: invalid start byte in Django
解決方法一: 使用 Python 的 UTF8 模式(推薦)
在導(dǎo)入命令前面加上 -Xutf8
參數(shù)
python -Xutf8 manage.py loaddata db.json
解決方案二: 魔改 Django 代碼
能用,但不推薦,實(shí)在沒辦法再來試這個(gè)方法
修改文件
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')
再進(jìn)行導(dǎo)入操作
參考資料
- https://docs.djangoproject.com/en/4.1/ref/django-admin/
- https://www.shubhamdipt.com/blog/django-transfer-data-from-sqlite-to-another-database/
- https://javaatpoint.com/solved-unicodedecodeerror-utf-8-codec-cant-decode-byte-0xff-in-position-0-invalid-start-byte/
- https://counter2015.com/2020/01/15/django-migration-sqlite-to-postgre/
- https://stackoverflow.com/questions/64457733/django-dumpdata-fails-on-special-characters
到此這篇關(guān)于Django切換數(shù)據(jù)庫和遷移數(shù)據(jù)詳解的文章就介紹到這了,更多相關(guān)Django切換數(shù)據(jù)庫和遷移數(shù)據(jù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
pytorch之深度神經(jīng)網(wǎng)絡(luò)概念全面整理
這篇文章主要介紹了pytorch之深度神經(jīng)網(wǎng)絡(luò)概念,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09Python實(shí)現(xiàn)24點(diǎn)小游戲
這篇文章主要為大家詳細(xì)介紹了Python實(shí)現(xiàn)24點(diǎn)小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09Python模擬伯努利試驗(yàn)和二項(xiàng)分布代碼實(shí)例
這篇文章主要介紹了Python模擬伯努利試驗(yàn)和二項(xiàng)分布代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05Django實(shí)現(xiàn)WebSSH操作物理機(jī)或虛擬機(jī)的方法
這篇文章主要介紹了Django實(shí)現(xiàn)WebSSH操作物理機(jī)或虛擬機(jī)的方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-11-11Python實(shí)現(xiàn)的檢測web服務(wù)器健康狀況的小程序
這篇文章主要介紹了Python實(shí)現(xiàn)的檢測web服務(wù)器健康狀況的小程序,本文使用socket庫來實(shí)現(xiàn),需要的朋友可以參考下2014-09-09centos+nginx+uwsgi+Django實(shí)現(xiàn)IP+port訪問服務(wù)器
這篇文章主要介紹了centos+nginx+uwsgi+Django實(shí)現(xiàn)IP+port訪問服務(wù)器,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11python進(jìn)階教程之函數(shù)對象(函數(shù)也是對象)
這篇文章主要介紹了python進(jìn)階教程之函數(shù)對象,函數(shù)對象是指函數(shù)也是對象,本文還講解了lambda函數(shù)、函數(shù)作為參數(shù)傳遞、map()函數(shù)、filter()函數(shù)、reduce()函數(shù)等內(nèi)容,需要的朋友可以參考下2014-08-08解決Python中導(dǎo)入自己寫的類,被劃紅線,但不影響執(zhí)行的問題
這篇文章主要介紹了解決Python中導(dǎo)入自己寫的類,被劃紅線,但不影響執(zhí)行的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07