2015年7月12日 星期日

Python筆記:Django(4) Model

Model

利用 Django Model 定義資料庫的結構 ( Schema ),並透過 Django 指令創建資料庫、資料表及欄位。

python的模型是ORM(object-relational mapping)的機制,透過操作python的類型與物件就能建立資料表和存取資料。在 Django 中,一個 model 就是一個 class。所有的 Django models 都必須繼承django.db.models.Model。
Store 類別:分別儲存店家名稱與其他資訊。
MenuItem 類別:一個用來存圖片檔案位置,另一個則是圖片標題(用在 HTML alt tag)。MenuItem 有一個指向Store 的 foreign key,叫做 store;這個 foreign key 在 Store 的 reverse attribute 則叫做menu_items。
#stores/models.py

class Store(models.Model):  

    name = models.CharField(max_length=20)  
    notes = models.TextField(blank=True, default='')  

class food(models.Model):  

    store = models.ForeignKey('Store', related_name='food')  
    name = models.CharField(max_length=20)  
    price = models.IntegerField()  
CharField 對應到資料庫的 VARCHAR。max_length 參數代表 VARCHAR 的長度。
TextField 對應到 TEXT。blank=True 代表本欄位可空白(注意不是可為 NULL!可為NULL 的欄位是使用 null=True);default 代表如果你在建立Store 物件時沒有輸入本欄位,預設會使用的值。
DecimalField,支援了浮點數的資料,如果是整數則把decimal_places設為0。
BooleanField真假值的資料
ForeignKey 是 Django 專門用來管理 foreign key 的 model field。
store = models.ForeignKey('Store', related_name='menu_items')
餐廳是一個資料表,但這裡面存在著一個關係,一家餐廳有多種食物,而每個食物都只屬於一家餐廳。這屬於一種Many-to-one的關係(n個food會對應到一家餐廳),這時我們需要使用ForeignKey(外鍵)來描述,這會使得每一個store能夠找到他所屬的所有食物,同樣的每一種Food也可以找到他屬於的餐廳。
現在程式已經可以認得這兩種 models 了。所有的模型都是繼承自django.db.models.Model的class,在之後我們會看到一個模型類別會對應到資料庫中的一張資料表,而實體化自此類別的物件就是資料表中的一筆一筆資料。
Django會把這些model的設定翻譯成各種資料庫的語言,這就好像是使用python對sql等語法做一個包覆(wrapper)而已。
python manage.py makemigrations stores告訴 Django 我們更新了 stores 中的 models。
$ python manage.py makemigrations stores
Migrations for 'stores':
  0001_initial.py:
    - Create model food
    - Create model Store
    - Add field store to food

migration資料檔

下述指令會對指定的應用做migration的檢查,如果模型有任何異動,則會產生新的migration檔,並放置在APP底下的migration資料夾;若不提供參數APP_NAME,則Django會對所有安裝好的APP做migration的檢查。
$ python manage.py makemigrations "APP_NAME"                                
Ex. Django 偵測到剛剛的 0001_initial 尚未與資料庫同步,並成功執行它。0001_initial.py,這代表了資料庫模型的第一版(0001)
$ python manage.py migrate stores
Operations to perform:
  Apply all migrations: stores
Running migrations:
  Rendering model states... DONE
  Applying stores.0001_initial... OK

寫 view,把前面製作的 model 顯示出來。

# Dinbendon/urls.py

from django.conf.urls import patterns, include, url
from django.contrib import admin
from stores.views import home,, store_list, store_detail

urlpatterns = [
     url(r'^$', home, name='home'),
     url(r'^store/$',store_list, name='store_list'),  #新增這行
     url(r'^store/(?P<pk>\d+)/$', store_detail, name='store_detail'), # 新增這行
     url(r'^admin/', include(admin.site.urls)),
     ]
接著是 store_list function。為了把店家列表顯示在這個頁面上要使用 Django 的 ORM query。
stores = Store.objects.all()
其中 Store.objects 會回傳一個 model manager。這個 manager 提供了 all method,回傳一個 query 物件。所以 stores 包含的是一個 query 物件,其中包含一個 SQL 指令,大致等同於下面的格式:
SELECT * FROM "stores";
#stores/views.py

from django.http import Http404 #在找不到對應物件時回應 404 Not Found
from django.shortcuts import render
from .models import Store


def home(request):
    return render(request, 'home.html')


def store_list(request):
    stores = Store.objects.all()
    return render(request, 'store_list.html', {'stores': stores})


def store_detail(request, pk):
    try:
        store = Store.objects.get(pk=pk)
    except Store.DoesNotExist:
        raise Http404
    return render(request, 'store_detail.html', {'store': store})
參考:
http://dokelung-blog.logdown.com/posts/220606-django-notes-5-model-and-database
https://docs.djangoproject.com/en/1.7/ref/models/fields/

沒有留言:

張貼留言