高見龍

iOS app/Ruby/Rails Developer & Instructor, 喜愛非主流的新玩具 :)

建立App

在上一章節我們介紹如何建立一個Django的專案,以及快速的建立起後台管理系統。但事實上它還是什麼都沒有,接下來我們要開始來幫這個空的專案加功能上去了。

建立App

這裡這個App跟現在我們常聽到手機的App是不一樣的東西,一個Django專案裡,可以有好幾個App,每個App通常代表的是一個功能。建立App的方法跟之前建立專案的方式有點像,只是關鍵字有些不同,例如我想加一個跟作者(author)有關的功能:

> python manage.py startapp author

這個指令會幫你在你的專案裡建立一個叫做author的資料夾,跟專案很像,裡面的有4個檔案,不過稍微有些些的不同:

> ls -l author
total 24
-rw-r--r--  1 eddie  wheel    0 10 18 16:05 __init__.py
-rw-r--r--  1 eddie  wheel   57 10 18 16:05 models.py
-rw-r--r--  1 eddie  wheel  383 10 18 16:05 tests.py
-rw-r--r--  1 eddie  wheel   26 10 18 16:05 views.py

__init__.py的目的跟之前專案一樣,是要告訴Python這裡是一個module,其它的看名字大概猜得出來,models.py是給Model用的,views.py則是給View用的,tests.py則是寫測試用的。

接著我們打開models.py,準備來寫一點程式碼了。

Model

在Django的Model是負責處理跟資料庫相關的事情,透過Python的類別、屬性跟方法,可以讓你像在操作物件一樣的操作資料表,而且可以避開一些可能的危險,例如SQL Injection。接下來我們來看看在Django的Model要怎麼寫。例如我們要來建一個作者的基本資料,假設一個作者的基本資料可能會有姓名電話地址Email 等欄位,我們在Model裡就這樣寫:

1
2
3
4
5
6
7
8
9
from django.db import models

# Create your models here.
class Profile(models.Model):
  name     = models.CharField(max_length = 50)
  age      = models.IntegerField()
  tel      = models.CharField(max_length = 30)
  address  = models.CharField(max_length = 100)
  email    = models.EmailField()

這裡的CharFieldIntegerField以及EmailField方法到時候會依照不同的資料庫,各別被轉換成適當的型態。這樣的好處就是,即使原本你的專案用的資料庫是SQLite,今天突然接到老闆或主管的命令說要換成MySQL,因為SQLite跟MySQL在某些欄位的定義可能不太一樣,在以前你可能需要重新調整資料庫存取的程式碼,但現在透過Django的Model來幫我們做這個型態的對應,程式碼不用幾乎不用修改就可以無痛的把資料庫整個換掉了。

接下來,我們要把這個App給安裝到INSTALLED_APPS裡,所以打開專案的settings.py,加上我們剛剛建立的App:

1
2
3
4
5
6
7
8
9
10
11
12
13
INSTALLED_APPS = (
  'django.contrib.auth',
  'django.contrib.contenttypes',
  'django.contrib.sessions',
  'django.contrib.sites',
  'django.contrib.messages',
  'django.contrib.staticfiles',
  # Uncomment the next line to enable the admin:
  'django.contrib.admin',
  # Uncomment the next line to enable admin documentation:
  # 'django.contrib.admindocs',
  'author',
)

這樣Django專案就知道我們有這個App了,然後執行python manage.py sql author,可以看到剛剛我們寫的那個Profile類別轉換成成SQL語法:

1
2
3
4
5
6
7
8
9
10
BEGIN;
CREATE TABLE "author_profile" (
    "id" integer NOT NULL PRIMARY KEY,
    "name" varchar(50) NOT NULL,
    "age" integer NOT NULL,
    "tel" varchar(30) NOT NULL,
    "address" varchar(100) NOT NULL,
    "email" varchar(75) NOT NULL
);
COMMIT;

原來的CharField會轉換成varchar,參數max_length = 50則被轉換成它的欄位長度,IntegerField轉換成integer,而且即使沒有特別註明,Django也預設在整個表格裡自動的加上了一個id的primary key(如果在MySQL就是autoincrement的欄位)。那EmailField是什麼? 因為Email欄位在開發網站的時候太常用到了,所以Django的Model就直接內建了一個叫做EmailField的方法,它會轉成換varchar(75),並同時還送了一些欄位驗證的方法,這個我們之後在表單處理的單元會再詳細討論。

當然這個Model不是只有讓你轉換成SQL這麼單純,它還有許多好用的方法讓你在開發網站可以少寫不少程式碼。

到這裡,我們其實還沒真正的把Profile類別轉換成資料庫的表格,你需要執行python manage.py syncdb,如果你寫的程式碼沒問題的話,應該會看到這個結果:

> bookstore  python manage.py syncdb
Creating tables ...
Creating table author_profile
Installing custom SQL ...
Installing indexes ...
No fixtures found.

執行syncdb之後,Django幫你建立了一個叫做author_profile的表格。Django的Model在建table的時候,預設會依照App名稱 + 類別名稱來建立,如果你想要改掉這個預設的設定,只要在Profile類別裡加上一個meta class,原來的程式碼就會變成這樣:

1
2
3
4
5
6
7
8
9
10
11
12
from django.db import models

# Create your models here.
class Profile(models.Model):
  name     = models.CharField(max_length = 50)
  age      = models.IntegerField()
  tel      = models.CharField(max_length = 30)
  address  = models.CharField(max_length = 100)
  email    = models.EmailField()

  class Meta(object):
    db_table = "profile"

要注意這個meta class是在原來的class再放一個class。這樣一來,轉出來的表格名稱就會是profile了。在Django的Model裡,Meta Class還有許多可以設定的屬性,更多細節請參考 https://docs.djangoproject.com/en/1.3/ref/models/options/

其實這個表格的名稱對Django的Model來說並不是那麼重要,因為我們在存取資料表的時候,還多透過了Django的ORM幫我們做表格及欄位對照的工作,所以即使使用預設有點囉嗦的表格名稱,或是用你自己設定的名稱,對Django的Model來說都是一樣的。

Django也有提供一個跟Python很像的shell,可以讓你直接透過指令來操作物件,不用寫SQL語法,一樣可以做到資料的新增/修改/查詢/刪除功能,接下來我們先停一下,來看看shell怎麼操作。

Comments