溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何使用Django 遷移數(shù)據(jù)庫(kù)

發(fā)布時(shí)間:2021-05-31 16:52:47 來(lái)源:億速云 閱讀:273 作者:Leah 欄目:開發(fā)技術(shù)

這篇文章將為大家詳細(xì)講解有關(guān)如何使用Django 遷移數(shù)據(jù)庫(kù),文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

遷移數(shù)據(jù)庫(kù)

為了讓 django 完成翻譯,創(chuàng)建好這些數(shù)據(jù)庫(kù)表,我們?cè)僖淮握?qǐng)出我的工程管理助手 manage.py。切換到 manage.py 文件所在的目錄(項(xiàng)目根目錄)下,分別運(yùn)行 pipenv run python manage.py makemigrations pipenv run python manage.py migrate 命令:

> pipenv run python manage.py makemigrations
Migrations for 'blog':
 blog\migrations\0001_initial.py
  - Create model Category
  - Create model Tag
  - Create model Post
  
> pipenv run python manage.py migrate
Operations to perform:
 Apply all migrations: admin, auth, blog, contenttypes, sessions
Running migrations:
 Applying contenttypes.0001_initial... OK
 Applying auth.0001_initial... OK
 Applying admin.0001_initial... OK
 Applying admin.0002_logentry_remove_auto_add... OK
 Applying admin.0003_logentry_add_action_flag_choices... OK
 Applying contenttypes.0002_remove_content_type_name... OK
 Applying auth.0002_alter_permission_name_max_length... OK
 Applying auth.0003_alter_user_email_max_length... OK
 Applying auth.0004_alter_user_username_opts... OK
 Applying auth.0005_alter_user_last_login_null... OK
 Applying auth.0006_require_contenttypes_0002... OK
 Applying auth.0007_alter_validators_add_error_messages... OK
 Applying auth.0008_alter_user_username_max_length... OK
 Applying auth.0009_alter_user_last_name_max_length... OK
 Applying auth.0010_alter_group_name_max_length... OK
 Applying auth.0011_update_proxy_permissions... OK
 Applying blog.0001_initial... OK
 Applying sessions.0001_initial... OK

當(dāng)我們執(zhí)行了 python manage.py makemigrations 后,django 在 blog 應(yīng)用的 migrations 目錄下生成了一個(gè) 0001_initial.py 文件,這個(gè)文件是 django 用來(lái)記錄我們對(duì)模型做了哪些修改的文件。目前來(lái)說(shuō),我們?cè)?models.py 文件里創(chuàng)建了 3 個(gè)模型類,django 把這些變化記錄在了 0001_initial.py 里。

不過(guò)此時(shí)還只是告訴了 django 我們做了哪些改變,為了讓 django 真正地為我們創(chuàng)建數(shù)據(jù)庫(kù)表,接下來(lái)又執(zhí)行了 python manage.py migrate 命令。django 通過(guò)檢測(cè)應(yīng)用中 migrations 目錄下的文件,得知我們對(duì)數(shù)據(jù)庫(kù)做了哪些操作,然后它把這些操作翻譯成數(shù)據(jù)庫(kù)操作語(yǔ)言,從而把這些操作作用于真正的數(shù)據(jù)庫(kù)。

你可以看到命令的輸出除了 Applying blog.0001_initial... OK 外,django 還對(duì)其它文件做了操作。這是因?yàn)槌宋覀冏约航⒌?blog 應(yīng)用外,django 自身還內(nèi)置了很多應(yīng)用,這些應(yīng)用本身也是需要存儲(chǔ)數(shù)據(jù)的??梢栽?settings.py 的 INSTALLED_APP 設(shè)置里看到這些應(yīng)用,當(dāng)然我們目前不必關(guān)心這些。

blogproject/settings.py

INSTALLED_APPS = [
  'django.contrib.admin',
  'django.contrib.auth',
  'django.contrib.contenttypes',
  'django.contrib.sessions',
  'django.contrib.messages',
  'django.contrib.staticfiles',
  'blog',
]

對(duì)于了解數(shù)據(jù)庫(kù)語(yǔ)言的人,你可以運(yùn)行下面的命令看看 django 究竟為我們做了什么:

> pipenv run python manage.py sqlmigrate blog 0001

你將看到輸出了經(jīng) django 翻譯后的數(shù)據(jù)庫(kù)表創(chuàng)建語(yǔ)句,這有助于你理解 django ORM 的工作機(jī)制。

選擇數(shù)據(jù)庫(kù)版本

我們沒(méi)有安裝任何的數(shù)據(jù)庫(kù)軟件,django 就幫我們遷移了數(shù)據(jù)庫(kù)。這是因?yàn)槲覀兪褂昧?Python 內(nèi)置的 SQLite3 數(shù)據(jù)庫(kù)。

SQLite3 是一個(gè)十分輕巧的數(shù)據(jù)庫(kù),它僅有一個(gè)文件。你可以看一到項(xiàng)目根目錄下多出了一個(gè) db.sqlite3 的文件,這就是 SQLite3 數(shù)據(jù)庫(kù)文件,django 博客的數(shù)據(jù)都會(huì)保存在這個(gè)數(shù)據(jù)庫(kù)文件里。

django 在 settings.py 里為我們做了一些默認(rèn)的數(shù)據(jù)庫(kù)配置:

blogproject/settings.py

## 其它配置選項(xiàng)...
DATABASES = {
  'default': {
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
  }
}
## 其它配置選項(xiàng)...

可以看到默認(rèn)的數(shù)據(jù)庫(kù)引擎就是使用的 SQLite3。

當(dāng)然一些人傾向于使用 MySQL 等大型數(shù)據(jù)庫(kù),至于 django 如何配置 MySQL 這里就不贅述了,你可以自行使用搜索引擎或者查閱 django 的官方文檔解決。對(duì)于一個(gè)小型博客而言,SQLite3 數(shù)據(jù)庫(kù)足以勝任。

用 django 的方式操作數(shù)據(jù)庫(kù)

數(shù)據(jù)庫(kù)最主要的操作就是往里面存入數(shù)據(jù)、從中取出數(shù)據(jù)、修改已保存的數(shù)據(jù)和刪除不再需要的數(shù)據(jù)(合稱 CURD)。和創(chuàng)建數(shù)據(jù)庫(kù)表一樣,django 為這些操作提供了一整套方法,從而把我們從數(shù)據(jù)庫(kù)語(yǔ)言中解放出來(lái)。我們不用學(xué)習(xí)如何利用數(shù)據(jù)庫(kù)語(yǔ)言去完成這些操作,只要簡(jiǎn)單地調(diào)用幾個(gè) Python 函數(shù)就可以滿足我們的需求。

存數(shù)據(jù)

先在命令行中來(lái)探索一下這些函數(shù),感受一下如何用 django 的方式來(lái)操作數(shù)據(jù)庫(kù)。在 manage.py 所在目錄下運(yùn)行 pipenv run python manage.py shell 命令:

> pipenv run python manage.py shell
Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:54:40) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>

這打開了一個(gè)交互式命令行。

首先我們來(lái)創(chuàng)建一個(gè)分類和一個(gè)標(biāo)簽:

>>> from blog.models import Category, Tag, Post
>>> c = Category(name='category test')
>>> c.save()
>>> t = Tag(name='tag test')
>>> t.save()

我們首先導(dǎo)入 3 個(gè)之前寫好的模型類,然后實(shí)例化了一個(gè) Category 類和一個(gè) Tag 類,為他們的屬性 name 賦了值。為了讓 django 把這些數(shù)據(jù)保存進(jìn)數(shù)據(jù)庫(kù),調(diào)用實(shí)例的 save 方法即可。

再創(chuàng)建一篇文章試試,但創(chuàng)建文章之前,我們需要先創(chuàng)建一個(gè) User,用于指定文章的作者。創(chuàng)建 User 的命令 django 已經(jīng)幫我們寫好了,依然是通過(guò) manage.py 來(lái)運(yùn)行。首先按住 Ctrl + c 退出命令交互欄(一次退不出就連續(xù)多按幾次),運(yùn)行 pipenv run python manage.py createsuperuser 命令并根據(jù)提示創(chuàng)建用戶:

> pipenv run python manage.py createsuperuser
Username (leave blank to use 'zmrenwu@163.com'): myuser
Email address: a@aa.com
Password:
Password (again):
Superuser created successfully.

運(yùn)行 python manage.py createsuperuser 開始創(chuàng)建用戶,之后會(huì)提示你輸入用戶名、郵箱、密碼和確認(rèn)密碼,按照提示輸入即可。 注意一點(diǎn)的是密碼輸入過(guò)程中不會(huì)有任何字符顯示,不要誤以為你的鍵盤出問(wèn)題了,正常輸入即可。 最后出現(xiàn) Superuser created successfully. 說(shuō)明用戶創(chuàng)建成功了。

再次運(yùn)行 python manage.py shell 進(jìn)入 Python 命令交互欄,開始創(chuàng)建文章:

>>> from blog.models import Category, Tag, Post
>>> from django.utils import timezone
>>> from django.contrib.auth.models import User
>>> user = User.objects.get(username='myuser')
>>> c = Category.objects.get(name='category test')
>>> p = Post(title='title test', body='body test', created_time=timezone.now(), modified_time=timezone.now(), category=c, author=user)
>>> p.save()

由于我們重啟了 shell,因此需要重新導(dǎo)入了 Category 、 Tag 、 Post 以及 User 。我們還導(dǎo)入了一個(gè) django 提供的輔助模塊 timezone,這是因?yàn)槲覀冃枰{(diào)用它的 now() 方法為 created_time modified_time 指定時(shí)間,容易理解 now 方法返回當(dāng)前時(shí)間。然后我們根據(jù)用戶名和分類名,通過(guò) get 方法取出了存在數(shù)據(jù)庫(kù)中的 User 和 Category (取數(shù)據(jù)的方法將在下面介紹)。接著我們?yōu)槲恼轮付?title 、 body 、 created_time 、 modified_time 值,并把它和前面創(chuàng)建的 Category 以及 User 關(guān)聯(lián)了起來(lái)。允許為空 excerpt 、 tags 我們就沒(méi)有為它們指定值了。

注意:

我們這里使用 get 方法根據(jù) Category 的 name 屬性的值獲取分類的一條記錄。 Category.objects.get(name='category test') 的含義是從數(shù)據(jù)庫(kù)中取出 name 的值為 category test 的分類記錄。確保數(shù)據(jù)庫(kù)中只有一條值為 category test 的記錄,否則 get 方法將返回一個(gè) MultipleObjectsReturned 異常。如果你不小心已經(jīng)存了多條記錄,請(qǐng)刪掉多余的記錄。如何刪除數(shù)據(jù)請(qǐng)看下文。

取數(shù)據(jù)

數(shù)據(jù)已經(jīng)存入數(shù)據(jù)庫(kù)了,現(xiàn)在要把它們?nèi)〕鰜?lái)看看:

>>> Category.objects.all()
<QuerySet [<Category: Category object>]>
>>> Tag.objects.all()
<QuerySet [<Tag: Tag object>]>
>>> Post.objects.all()
<QuerySet [<Post: Post object>]>
>>>

objects 是我們的模型管理器,它為我們提供一系列從數(shù)據(jù)庫(kù)中取數(shù)據(jù)方法,這里我們使用了 all 方法,表示我們要把對(duì)應(yīng)的數(shù)據(jù)全部取出來(lái)。可以看到 all 方法都返回了數(shù)據(jù),這些數(shù)據(jù)應(yīng)該是我們之前存進(jìn)去的,但是顯示的字符串有點(diǎn)奇怪,無(wú)法看出究竟是不是我們之前存入的數(shù)據(jù)。為了讓顯示出來(lái)的數(shù)據(jù)更加人性化一點(diǎn),我們?yōu)?3 個(gè)模型分別增加一個(gè) __str__ 方法:

blog/models.py
class Category(models.Model):
  ...
  def __str__(self):
    return self.name
class Tag(models.Model):
  ...
  def __str__(self):
    return self.name
class Post(models.Model):
  ...
  def __str__(self):
    return self.title

定義好 __str__ 方法后,解釋器顯示的內(nèi)容將會(huì)是 __str__ 方法返回的內(nèi)容。這里 Category 返回分類名 name , Tag 返回標(biāo)簽名,而 Post 返回它的 title 。

先按 Ctrl + c 退出 Shell,再重新運(yùn)行 python manage.py shell 進(jìn)入 Shell。

>>> from blog.models import Category, Tag, Post
>>> Category.objects.all()
<QuerySet [<Category: category test>]>
>>> Tag.objects.all()
<QuerySet [<Tag: tag test>]>
>>> Post.objects.all()
<QuerySet [<Post: title test>]>
>>> Post.objects.get(title='title test')
<Post: title test>

可以看到返回的是我們之前存入的數(shù)據(jù)。

此外我們?cè)趧?chuàng)建文章時(shí)提到了通過(guò) get 方法來(lái)獲取數(shù)據(jù),這里 all 方法和 get 方法的區(qū)別是: all 方法返回全部數(shù)據(jù),是一個(gè)類似于列表的數(shù)據(jù)結(jié)構(gòu)(QuerySet);而 get 返回一條記錄數(shù)據(jù),如有多條記錄或者沒(méi)有記錄, get 方法均會(huì)拋出相應(yīng)異常。

改數(shù)據(jù)

嘗試修改數(shù)據(jù):

>>> c = Category.objects.get(name='category test')
>>> c.name = 'category test new'
>>> c.save()
>>> Category.objects.all()
<QuerySet [<Category: test category new>]>

首先通過(guò) get 方法根據(jù)分類名 name 獲取值為 category test 到分類,修改它的 name 屬性為新的值 category test new,然后調(diào)用 save 方法把修改保存到數(shù)據(jù)庫(kù),之后可以看到數(shù)據(jù)庫(kù)返回的數(shù)據(jù)已經(jīng)是修改后的值了。 Tag 、 Post 的修改也一樣。

刪數(shù)據(jù)

刪除掉數(shù)據(jù):

>>> p = Post.objects.get(title='title test')
>>> p
<Post: title test>
>>> p.delete()
(1, {'blog.Post_tags': 0, 'blog.Post': 1})
>>> Post.objects.all()
<QuerySet []>

先根據(jù)標(biāo)題 title 的值從數(shù)據(jù)庫(kù)中取出 Post ,保存在變量 p 中,然后調(diào)用它的 delete 方法,最后看到 Post.objects.all() 返回了一個(gè)空的 QuerySet(類似于一個(gè)列表),表明數(shù)據(jù)庫(kù)中已經(jīng)沒(méi)有 Post,Post 已經(jīng)被刪除了。

這就是 django 對(duì)數(shù)據(jù)庫(kù)增、刪、改、查的操作。除了上述演示的方法外,django 還為我們提供了大量其它的方法,這些方法有一部分會(huì)在教程中使用,用到時(shí)我會(huì)講解它們的用法。但以后你開發(fā)自己的項(xiàng)目時(shí),你就需要通過(guò)閱讀django 的官方文檔 來(lái)了解有哪些方法可用以及如何使用它們。

關(guān)于如何使用Django 遷移數(shù)據(jù)庫(kù)就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI