通過資料庫向Django模型添加欄位的樣本

來源:互聯網
上載者:User
首先借用書本(book)的這個資料模型:

from django.db import modelsclass 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.nameclass 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


添加欄位
當要向一個產品設定表(或者說是model)添加一個欄位的時候,要使用的技巧是利用Django不關心表裡是否包含model裡所沒有的列的特性。 策略就是現在資料庫裡加入欄位,然後同步Django的模型以包含新欄位。

然而 這裡有一個雞生蛋蛋生雞的問題 ,由於要想瞭解新增列的SQL語句,你需要使用Django的 manage.py sqlall命令進行查看 ,而這又需要欄位已經在模型裡存在了。 (注意:你並 不是非得使用與Django相同的SQL語句建立新的欄位,但是這樣做確實是一個好主意 ,它能讓一切都保持同步。)

這個雞-蛋的問題的解決方案是在開發人員環境裡而不是發布環境裡實現這個變化。 (你正使用的是測試/開發環境,對吧?)下面是具體的實施步驟。

首先,進入開發環境(也就是說,不是在發布環境裡):

在你的模型裡添加欄位。

運行 manage.py sqlall [yourapp] 來測試模型新的 CREATE TABLE 語句。 注意為新欄位的列定義。

開啟你的資料庫的互動命令介面(比如, psql 或mysql , 或者可以使用 manage.py dbshell )。 執行 ALTER TABLE 語句來添加新列。

使用Python的manage.py shell,通過匯入模型和選中表單(例如, MyModel.objects.all()[:5] )來驗證新的欄位是否被正確的添加 ,如果一切順利,所有的語句都不會報錯。

然後在你的產品伺服器上再實施一遍這些步驟。

啟動資料庫的互動介面。

執行在開發環境步驟中,第三步的ALTER TABLE語句。

將新的欄位加入到模型中。 如果你使用了某種版本控制工具,並且在第一步中,已經提交了你在開發環境上的修改,現在,可以在生產環境中更新你的代碼了(例如,如果你使用Subversion,執行svn update。

重新啟動Web server,使修改生效。

讓我們實踐下,比如添加一個num_pages欄位到第五章中Book模型。首先,我們會把開發環境中的模型改成如下形式:

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


然後,我們運行命令manage.py sqlall books 來查看CREATE TABLE語句。 語句的具體內容取決與你所使用的資料庫, 大概是這個樣子:

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

接下來,我們要在開發環境上運行資料庫用戶端,如果是PostgreSQL,運行 psql,,然後,我執行如下語句。

ALTER TABLE books_book ADD COLUMN num_pages integer;

添加 非NULL 欄位

這裡有個微妙之處值得一提。 在我們添加欄位num_pages的時候,我們使用了 blank=True 和 null=True 選項。 這是因為在我們第一次建立它的時候,這個資料庫欄位會含有空值。

然而,想要添加不能含有空值的欄位也是可以的。 要想實現這樣的效果,你必須先建立 NULL 型的欄位,然後將該欄位的值填充為某個預設值,然後再將該欄位改為 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 選項。

執行ALTER TABLE之後,我們要驗證一下修改結果是否正確。啟動python並執行下面的代碼:

>>> from mysite.books.models import Book>>> Book.objects.all()[:5]

如果沒有異常發生,我們將切換到生產伺服器,然後在生產環境的資料庫中執行命令ALTER TABLE 然後我們更新生產環境中的模型,最後重啟web伺服器。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.