修改django-模型方法

Migrations

Django中對Model進行修改是件麻煩的事情,syncdb命令僅僅建立數據庫裏尚未的表,它並不對已存在的數據表進行同步修改,也不處理數據模型的刪除。 若是你新增或修改數據模型裏的字段,或是刪除了一個數據模型,你須要手動在數據庫裏進行相應的修改或者使用South。Django 1.7中已經集成了South的代碼,提供了3個新命令:php

  • migrate: 用於執行遷移動做,具備syncdb的功能html

  • makemigrations: 基於當前的model建立新的遷移策略文件python

  • sqlmigrate: 顯示遷移的SQL語句,具備sqlall的功能mysql

使用起來很簡單,對Model作了修改後,使用makemigrations記錄修改:git

$ python manage.py makemigrations
Migrations for 'books':
  0003_auto.py:
    - Alter field author on book

你的Model會被掃描, 而後與migrations文件夾中之前的版本做比較, 而後生成本次遷移文件。sql

有了新的migration文件,就可使用migrate修改數據庫模式:shell

$ python manage.py migrate
Operations to perform:
  Synchronize unmigrated apps: sessions, admin, messages, auth, staticfiles, contenttypes
  Apply all migrations: books
Synchronizing apps without migrations:
  Creating tables...
  Installing custom SQL...
  Installing indexes...
Installed 0 object(s) from 0 fixture(s)
Running migrations:
  Applying books.0003_auto... OK

也能夠針對單獨的app生成migration:數據庫

$ python manage.py makemigrations your_app_label

也能夠對數據庫中的數據進行修改,首先創建一個空的migration文件:django

python manage.py makemigrations --empty yourappname

文件的內容以下:json

# -*- coding: utf-8 -*-from django.db import models, migrationsclass Migration(migrations.Migration):

    dependencies = [
        ('yourappname', '0001_initial'),
    ]

    operations = [
    ]

若是想修改某個Model例如Person的數據,設置其name字段:

# -*- coding: utf-8 -*-from django.db import models, migrationsdef combine_names(apps, schema_editor):  # We can't import the Person model directly as it may be a newer  # version than this migration expects. We use the historical version.  Person = apps.get_model("yourappname", "Person")  for person in Person.objects.all():    person.name = "%s %s" % (person.first_name, person.last_name)    person.save()class Migration(migrations.Migration):  dependencies = [    ('yourappname', '0001_initial'),  ]  operations = [    migrations.RunPython(combine_names),  ]

最後運行 python manage.py migrate 便可。這樣Person中的全部對象的name字段都設置好了。

依據Model修改關係數據庫是開發中的一個重要的問題,解決這個問題能夠提高開發速度,不過要在生產環境中隨便使用migrate操做數據庫仍是很危險的,有時候須要手動修改數據庫。

手動修改數據庫

當處理模型修改的時候:

  • 若是模型包含一個不曾在數據庫裏創建的字段,Django會報出錯信息。 當你第一次用Django的數據庫API請求表中不存在的字段時會致使錯誤。

  • Django不關心數據庫表中是否存在未在模型中定義的列。

  • Django不關心數據庫中是否存在未被模型表示的table。

添加字段

  1. 在你的模型裏添加字段。下例向Book模型添加num_pages字段:

    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 
  1. 運行manage.py sqlall yourappname來測試模型新的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);
  1. 開啓你的數據庫的交互命令界面(好比,psql或者mysql,或者可使用manage.py dbshell。 執行ALTER TABLE語句來添加新列。

    ALTER TABLE books_book ADD COLUMN num_pages integer;  

添加 非NULL 字段

先建立 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;

添加ForeignKey或ManyToManyField

添加外鍵便是添加key_id的integer字段,添加多對多字段是建立一個新的數據表。

刪除字段

比較簡單,將表中的某列刪掉便可

ALTER TABLE books_book DROP COLUMN num_pages;

使用sqlite3時,會有些麻煩,sqlite3不支持刪除列操做,只有有限地 ALTER TABLE 支持。你可使用它來在表的末尾增長一列,可更改表的名稱。 若是須要對錶結構作更復雜的改變,則必須從新建表。重建時能夠先將已存在的數據放到一個臨時表中,刪除原表, 建立新表,而後將數據從臨時表中複製回來。

如,假設有一個 t1 表,其中有 "a", "b", "c" 三列, 若是要刪除列 c :

BEGIN TRANSACTION;CREATE TEMPORARY TABLE t1_backup(a,b);INSERT INTO t1_backup SELECT a,b FROM t1;DROP TABLE t1;CREATE TABLE t1(a,b);INSERT INTO t1 SELECT a,b FROM t1_backup;DROP TABLE t1_backup;COMMIT;

刪除多對多關聯字段

刪掉多對多關聯的數據表便可

DROP TABLE books_book_authors;

刪除模型

刪除數據表便可

DROP TABLE books_book;

數據遷移

django 項目提供了一個導出的方法 python manage.py dumpdata, 不指定 appname 時默認爲導出全部的app

python manage.py dumpdata myapp > myapp.json

導出的文件內容格式:

[
  {
    "model": "myapp.person",
    "pk": 1,
    "fields": {
      "first_name": "John",
      "last_name": "Lennon"
    }
  },
  {
    "model": "myapp.person",
    "pk": 2,
    "fields": {
      "first_name": "Paul",
      "last_name": "McCartney"
    }
  }]

數據導入:

python manage.py loaddata myapp.json

導出用戶數據:

python manage.py dumpdata auth > auth.json

--------------------------------

咱們已經實現了賣方的產品維護界面,根據最初的需求,還要爲買方實現一個目錄頁:買方經過這個界面瀏覽產品並能夠加入購物車。經過進一步需求調研,瞭解到產品有一個「上架時間」,在這個時間以後的產品才能被買方看到。而且買方應該先看到最新的產品。

咱們注意到,這個「新需求」須要對Product進行調整,增長一個日期屬性date_available來保存「上架時間」。如同開發新功能同樣,在修改的時候也應該從model開始。

爲Model類增長一個屬性很容易:

 

  1. class Product(models.Model):

  2. title = models.CharField(max_length=100,unique=True)

  3. description     = models.TextField()

  4. image_url = models.URLField(max_length=200)

  5. price = models.DecimalField(max_digits=8,decimal_places=2)

  6. date_available = models.DateField()


問題在於,model類的改變須要對數據庫表也進行一樣的修改。你可能想到前面介紹過的python manage.py syncdb, 可是很遺憾這個命令如今不起做用了。由於syncdb僅僅建立數據庫裏尚未的表,它 並不 對你數據模型的修改進行同步,也不處理數據模型的刪除。 若是你新增或修改數據模型裏的字段,或是刪除了一個數據模型,你須要手動在數據庫裏進行相應的修改。 固然,在開發環境你能夠drop相應的表,而後運行syncdb從新建立。可是這樣作對於發佈環境沒有任何幫助,因此咱們最好這樣作:
1. 使用sqlall查看模型新的 CREATE TABLE 語句。 查看新建立的字段:
$ python manage.py sqlall depotapp
BEGIN;
CREATE TABLE "depotapp_product" (
"id" integer NOT NULL PRIMARY KEY,
"title" varchar(100) NOT NULL UNIQUE,
"description" text NOT NULL,
"image_url" varchar(200) NOT NULL,
"price" decimal NOT NULL,
"date_available" date NOT NULL
)
;
COMMIT;


2. 使用數據庫命令行工具,或客戶端工具,或者django提供的dbshell工具增長字段:
$ python manage.py dbshell
sqlite> begin;
sqlite> alter table depotapp_product add column date_available date not null default 0;
sqlite> commit;

3. 驗證數據庫:
$ python manage.py shell
>>> from depot.depotapp.models import Product
>>> Product.objects.all()
若是沒有異常發生,則能夠在發佈環境進行上述修改。

 

以上是在模型中增長一個屬性的步驟。其餘對模型的修改可能還有:

刪除字段——drop column

刪除模型——drop table

刪除多對多關聯——drop table (自動生成的關聯表)

也須要參考上述的步驟進行。

相關文章
相關標籤/搜索