通過(guò)數(shù)據(jù)庫(kù)向Django模型添加字段的示例
首先借用書(shū)本(book)的這個(gè)數(shù)據(jù)模型:
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
def __unicode__(self):
return self.name
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
def __unicode__(self):
return self.title
添加字段
當(dāng)要向一個(gè)產(chǎn)品設(shè)置表(或者說(shuō)是model)添加一個(gè)字段的時(shí)候,要使用的技巧是利用Django不關(guān)心表里是否包含model里所沒(méi)有的列的特性。 策略就是現(xiàn)在數(shù)據(jù)庫(kù)里加入字段,然后同步Django的模型以包含新字段。
然而 這里有一個(gè)雞生蛋蛋生雞的問(wèn)題 ,由于要想了解新增列的SQL語(yǔ)句,你需要使用Django的 manage.py sqlall命令進(jìn)行查看 ,而這又需要字段已經(jīng)在模型里存在了。 (注意:你并 不是非得使用與Django相同的SQL語(yǔ)句創(chuàng)建新的字段,但是這樣做確實(shí)是一個(gè)好主意 ,它能讓一切都保持同步。)
這個(gè)雞-蛋的問(wèn)題的解決方法是在開(kāi)發(fā)者環(huán)境里而不是發(fā)布環(huán)境里實(shí)現(xiàn)這個(gè)變化。 (你正使用的是測(cè)試/開(kāi)發(fā)環(huán)境,對(duì)吧?)下面是具體的實(shí)施步驟。
首先,進(jìn)入開(kāi)發(fā)環(huán)境(也就是說(shuō),不是在發(fā)布環(huán)境里):
在你的模型里添加字段。
運(yùn)行 manage.py sqlall [yourapp] 來(lái)測(cè)試模型新的 CREATE TABLE 語(yǔ)句。 注意為新字段的列定義。
開(kāi)啟你的數(shù)據(jù)庫(kù)的交互命令界面(比如, psql 或mysql , 或者可以使用 manage.py dbshell )。 執(zhí)行 ALTER TABLE 語(yǔ)句來(lái)添加新列。
使用Python的manage.py shell,通過(guò)導(dǎo)入模型和選中表單(例如, MyModel.objects.all()[:5] )來(lái)驗(yàn)證新的字段是否被正確的添加 ,如果一切順利,所有的語(yǔ)句都不會(huì)報(bào)錯(cuò)。
然后在你的產(chǎn)品服務(wù)器上再實(shí)施一遍這些步驟。
啟動(dòng)數(shù)據(jù)庫(kù)的交互界面。
執(zhí)行在開(kāi)發(fā)環(huán)境步驟中,第三步的ALTER TABLE語(yǔ)句。
將新的字段加入到模型中。 如果你使用了某種版本控制工具,并且在第一步中,已經(jīng)提交了你在開(kāi)發(fā)環(huán)境上的修改,現(xiàn)在,可以在生產(chǎn)環(huán)境中更新你的代碼了(例如,如果你使用Subversion,執(zhí)行svn update。
重新啟動(dòng)Web server,使修改生效。
讓我們實(shí)踐下,比如添加一個(gè)num_pages字段到第五章中Book模型。首先,我們會(huì)把開(kāi)發(fā)環(huán)境中的模型改成如下形式:
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
**num_pages = models.IntegerField(blank=True, null=True)**
def __unicode__(self):
return self.title
然后,我們運(yùn)行命令manage.py sqlall books 來(lái)查看CREATE TABLE語(yǔ)句。 語(yǔ)句的具體內(nèi)容取決與你所使用的數(shù)據(jù)庫(kù), 大概是這個(gè)樣子:
CREATE TABLE "books_book" (
"id" serial NOT NULL PRIMARY KEY,
"title" varchar(100) NOT NULL,
"publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id"),
"publication_date" date NOT NULL,
"num_pages" integer NULL
);
新加的字段被這樣表示:
"num_pages" integer NULL
接下來(lái),我們要在開(kāi)發(fā)環(huán)境上運(yùn)行數(shù)據(jù)庫(kù)客戶端,如果是PostgreSQL,運(yùn)行 psql,,然后,我執(zhí)行如下語(yǔ)句。
ALTER TABLE books_book ADD COLUMN num_pages integer;
添加 非NULL 字段
這里有個(gè)微妙之處值得一提。 在我們添加字段num_pages的時(shí)候,我們使用了 blank=True 和 null=True 選項(xiàng)。 這是因?yàn)樵谖覀兊谝淮蝿?chuàng)建它的時(shí)候,這個(gè)數(shù)據(jù)庫(kù)字段會(huì)含有空值。
然而,想要添加不能含有空值的字段也是可以的。 要想實(shí)現(xiàn)這樣的效果,你必須先創(chuàng)建 NULL 型的字段,然后將該字段的值填充為某個(gè)默認(rèn)值,然后再將該字段改為 NOT NULL 型。 例如:
BEGIN; ALTER TABLE books_book ADD COLUMN num_pages integer; UPDATE books_book SET num_pages=0; ALTER TABLE books_book ALTER COLUMN num_pages SET NOT NULL; COMMIT;
如果你這樣做,記得你不要在模型中添加 blank=True 和 null=True 選項(xiàng)。
執(zhí)行ALTER TABLE之后,我們要驗(yàn)證一下修改結(jié)果是否正確。啟動(dòng)python并執(zhí)行下面的代碼:
>>> from mysite.books.models import Book >>> Book.objects.all()[:5]
如果沒(méi)有異常發(fā)生,我們將切換到生產(chǎn)服務(wù)器,然后在生產(chǎn)環(huán)境的數(shù)據(jù)庫(kù)中執(zhí)行命令A(yù)LTER TABLE 然后我們更新生產(chǎn)環(huán)境中的模型,最后重啟web服務(wù)器。
相關(guān)文章
Python使用scipy模塊實(shí)現(xiàn)一維卷積運(yùn)算示例
這篇文章主要介紹了Python使用scipy模塊實(shí)現(xiàn)一維卷積運(yùn)算,結(jié)合實(shí)例形式分析了scipy模塊的功能及使用scipy模塊進(jìn)行一維卷積運(yùn)算的相關(guān)操作技巧,需要的朋友可以參考下2019-09-09
OpenCV圖像縮放resize各種插值方式的比較實(shí)現(xiàn)
OpenCV提供了resize函數(shù)來(lái)改變圖像的大小,本文主要介紹了OpenCV圖像縮放resize各種插值方式的比較實(shí)現(xiàn),分享給大家,感興趣的可以了解一下2021-06-06
簡(jiǎn)單談?wù)凱ython中的幾種常見(jiàn)的數(shù)據(jù)類(lèi)型
Python 中的變量不需要聲明。每個(gè)變量在使用前都必須賦值,變量賦值以后該變量才會(huì)被創(chuàng)建。在 Python 中,變量就是變量,它沒(méi)有類(lèi)型,我們所說(shuō)的"類(lèi)型"是變量所指的內(nèi)存中對(duì)象的類(lèi)型。2017-02-02
使用Pandas對(duì)列名和索引進(jìn)行重命名的幾種常見(jiàn)方法
在數(shù)據(jù)分析和處理中,Pandas是一個(gè)非常強(qiáng)大的工具,它提供了靈活的數(shù)據(jù)結(jié)構(gòu)和豐富的操作方法,使得數(shù)據(jù)處理變得更加簡(jiǎn)單高效,其中,對(duì)數(shù)據(jù)的列名和索引進(jìn)行重命名是常見(jiàn)的需求之一,本文將從基礎(chǔ)概念出發(fā),逐步深入探討如何使用Pandas對(duì)列名和索引進(jìn)行重命名2024-12-12
python全棧要學(xué)什么 python全棧學(xué)習(xí)路線
在本文中小編給大家整理了關(guān)于python全棧要學(xué)什么以及python全棧學(xué)習(xí)路線的知識(shí)點(diǎn)內(nèi)容,需要的朋友們參考下。2019-06-06
一文帶你搞懂Python中isinstance和type的區(qū)別
在Python中,我們經(jīng)常需要檢查一個(gè)對(duì)象的類(lèi)型,Python提供了兩種方法來(lái)獲取對(duì)象的類(lèi)型:isinstance和type,這兩種方法有什么區(qū)別呢,本文將詳細(xì)介紹這兩種方法的區(qū)別和使用,需要的朋友可以參考下2023-06-06
python識(shí)別圖像并提取文字的實(shí)現(xiàn)方法
這篇文章主要介紹了python識(shí)別圖像并提取文字的實(shí)現(xiàn)方法,2019-06-06

