Python開發入門與實戰5-django模型

5.Django模型

  在當今的Web 應用中,主觀邏輯常常牽涉到與數據庫的交互,數據庫驅動網站。在後臺鏈接數據庫服務器,從中取出一些數據,而後在 Web 頁面用各類各樣的格式展現這些數據。這個網站也可能會向訪問者提供修改數據庫數據的方法。html

  本章深刻介紹了該功能: Django 數據庫層。本例咱們使用Python安裝包自帶的SQLite數據庫來演示Django如何訪問數據庫。python

5.1.SQLite數據庫

  首先咱們使用數據庫訪問工具Navicat premium來在mysite目錄下建立SQLite數據庫文件。Navicat premium下載地址http://navicat-premium.softonic.cn/mysql

運行Navicat premium工具,在主界面的菜單中選擇文件->新建鏈接-SQLite以下圖:sql

  在對話框中選擇新建SQLite3數據庫文件,數據庫文件名命名爲:MyDB.db後點擊肯定按鈕。以下圖:shell

  數據庫文件鏈接後,界面展開以下圖:數據庫

5.2. 執行SQL的訪問數據庫模式

  如今咱們能夠經過執行SQL的方式來訪問數據庫,獲取數據並更新到咱們的動態頁面中,修改views.py把current_datetime視圖獲取時間的方式修改成經過執行SQL 「select datetime() as now」讀取數據庫的時間,修改後代碼以下:django

from django.shortcuts import render_to_response

import sqlite3 def current_datetime(request):

  db = sqlite3.connect('C:\My Files\Python Projects\mysite\Mydb.db')   cursor = db.cursor()   cursor.execute('select datetime() as now')   now = [row[0] for row in cursor.fetchall()]   db.close()   return render_to_response('current_datetime.html', {'current_date': now})

 

  如上代碼,我是通過代碼重構,current_datetime實現了讀取數據庫的當前時間,可是這種把SQL與業務邏輯徹底綁定的開發模式會存爲未來維護和升級的噩夢。業務變動致使的業務邏輯調整,進而須要調整到SQL代碼,最後就與數據庫設計深度綁定,尤爲切換數據庫時因爲各個數據庫支持的SQL不徹底一致,應用的遷移將花費的代價更大。服務器

  好在Django提供了本身的對象持久化模型,實現了對象模型到數據庫表的映射機制,接下來咱們進入Django的對象模型來實現數據庫數據的讀取。session

5.3. 經過模型訪問數據庫模式

  Django 牢牢地遵循這種 MVC 模式,能夠稱得上是一種 MVC 框架。MVC 是一種使用 MVC(Model View Controller 模型-視圖-控制器)設計建立 Web 應用程序的模式。oracle

5.3.1. 數據庫配置

  咱們來看看 Django 數據庫模型層的功能吧。 首先,須要作些初始配置;須要告訴Django使用什麼數據庫以及如何鏈接數據庫。本例咱們使用SQLite數據庫文件系統來存儲數據。

  如前面章節提到的 TEMPLATE_DIRS 同樣,數據庫配置也是在Django的配置文件settings.py裏。默認生成的數據庫配置以下:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': '',                      # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

  修改配置文件以下:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends. sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': ' C:\My Files\Python Projects\mysite\MyDB.db',  # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

  完成設置並保存以後咱們測試一下配置。 一樣,在「mysite」項目目錄下執行前面提到的「python manage.py shell」環境來進行測試。

輸入下面的命令來測試數據庫配置是否正確:

>>> from django.db import connection
>>> cursor = connection.cursor()

  若是沒有顯示什麼錯誤信息,那麼數據庫配置是正確的。

5.4. 第一個應用程序

  數據庫鏈接正常工做後,讓咱們來建立一個 Django app,一個包含模型,視圖和Django代碼,而且形式爲獨立Python包的完整Django應用。

在這裏先解釋說明一些術語,初學者可能會混淆它們。在第二章咱們已經建立了一個project,那麼 project 和 app 之間不一樣之處是什麼呢?它們的區別就是一個是配置另外一個是業務代碼

一個project包含不少個Django app。project的做用是提供這些應用統一配置文件,好比前面定義數據庫鏈接信息, 須要裝載的app列表,TEMPLATE_DIRS等。

一個app是一套業務功能的集合,一般包括模型和視圖,按Python的包結構的方式存在。app的一個關鍵點是它們是很容易移植到其餘project和被多個project複用。

Django系統對app有一個約定: 要使用Django的數據庫層(模型),必須建立一個Django app,模型存放在apps中。在 「mysite」 項目文件下輸入下面的命令來建立「inventory」的app,本例將以簡單出入庫業務來講明Django的模型。

>>> python manage.py startapp inventory

  增長子目錄及子目錄inventory 包含文件以下圖:

inventory /
    __init__.py
    models.py
    tests.py
    views.py

5.4.1. 第一個模型

  在本章和後續章節裏,咱們將實現一個基本的庫存管理(庫存/出入庫)的數據庫結構上,這也是一個做者遇到過的比較典型關於業務及業務事務的例子。

庫存管理涉及的基本概念、字段和關係:

    物料:物料編號、物料名稱、備註。

    物料庫存:物料編號、物料名稱、庫存數量。

    入庫單:入庫單編號、入庫時間、操做人,物料編碼、物料名稱、入庫數量。

  注意:本模型爲便於闡述簡化設計入庫單爲單一物料入庫單,後面的章節咱們會逐步擴展這一模型以符合實際的須要。

  物料與物料庫存是一個one-to-one關係, 對於入庫單模型來講其與物料的關係是many-to-many關係。

  接下來咱們用Python代碼來描述它們。 打開由建立的inventory \models.py 並輸入下面的內容:

from django.db import models

# Create your models here.

class Item(models.Model):
    ItemId = models.AutoField(primary_key=True)
    ItemCode = models.CharField(max_length=50)
ItemName
= models.CharField(max_length=50) Remark = models.CharField(max_length=200) class Inventory (models.Model): InventoryId = models.AutoField(primary_key=True) Item = models.ForeignKey(Item, null=False) Amount = models.IntegerField(null=True) class InStockBill(models.Model): InStockBillId = models.AutoField(primary_key=True) InStockBillCode = models.CharField(max_length=40) InStockDate = models.DateTimeField(null=True) Operator = models.CharField(max_length=40) Item = models.ForeignKey(Item, null=False) Amount = models.IntegerField(null=True)

 

5.4.2. 裝載模型

  完成上面的模型代碼後,如今讓咱們經過Django在數據庫中建立這些表。第一步是在 Django 項目中裝載這些模型。 將 inventory app 添加到配置文件的裝載應用列表中便可。

  編輯 settings.py 文件, 找到 INSTALLED_APPS 設置。 INSTALLED_APPS 告訴 Django 項目須要裝載哪些 app模型。 缺省生成代碼在後面添加「inventory」到「INSTALLED_APPS」的末尾,注意:只配置應用名稱,沒有項目名稱,代碼以下:

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',
    'inventory', )


  如今咱們能夠建立數據庫表了。 首先,用下面的命令驗證模型的有效性:

python manage.py validate

validate 命令檢查你的模型的語法和邏輯是否正確。 若是一切正常,你會看到 0 errors found 消息。若是出錯,根據錯誤信息來幫助你修正你的模型。

python manage.py sqlall inventory

  執行以後,輸出以下:

BEGIN;
CREATE TABLE "inventory_item" (
    "ItemId" integer NOT NULL PRIMARY KEY,
    "ItemCode" varchar(50) NOT NULL,
    "ItemName" varchar(50) NOT NULL
);
CREATE TABLE "inventory_inventory" (
    "InventoryId" integer NOT NULL PRIMARY KEY,
    "Item_id" integer NOT NULL REFERENCES "inventory_item" ("ItemId"),
    "Amount" integer
);
CREATE TABLE "inventory_instockbill" (
    "InStockBillId" integer NOT NULL PRIMARY KEY,
    "InStockBillCode" varchar(40) NOT NULL,
    "InStockDate" datetime,
    "Operator" varchar(40) NOT NULL,
    "Item_id" integer NOT NULL REFERENCES "inventory_item" ("ItemId"),
    "Amount" integer
);
CREATE INDEX "inventory_inventory_70e6447b" ON "inventory_inventory" ("Item_id");
CREATE INDEX "inventory_instockbill_70e6447b" ON "inventory_instockbill" ("Item_id");
COMMIT;

  

 

sqlall 命令並無在數據庫中真正建立數據表,只是把SQL語句段打印出來,這樣你能夠看到Django究竟會作些什麼。

Django提供了一種更爲簡易的提交SQL語句至數據庫的方法:「syncdb」命令

python manage.py syncdb

  syncdb 命令是同步你的模型到數據庫的一個簡單方法。 它會根據 INSTALLED_APPS 裏設置的app來檢查數據庫, 若是表不存在,它就會建立它。

表建立結果以下圖:

 

5.4.3.數據訪問

  運行 python manage.py shell 並輸入下面的內容試試看

>>> from inventory.models import Item
>>> itm1 = Item(ItemCode='003',ItemName='螺帽')
>>> itm1.save()

  咱們查看數據庫看發生了什麼,物料數據被保存到數據庫中了,以下圖:

  咱們在數據庫工具端增長一條記錄:000,螺桿以下圖:

  接下來再命令行窗口中錄入以下命令:

>>> items =Item.objects.all()
>>> print items[1].ItemName
螺桿
>>>

  咱們經過Item.objects.all()獲取了全部的Item列表數據(當前只有兩條)。

>>> itm2 = Item.objects.get(ItemId = 2)
>>> print itm2.ItemName
螺桿
>>> itm2.ItemName=u'5mm螺桿'
>>> itm2.save()
>>>

   修改對象屬性後,保存數據,對象屬性會同步到相應的數據行。

5.4.3.1. 保存有外鍵關聯的模型

  咱們建立一個入庫單對象,並嘗試如何正確的保存該對象到數據庫中,命令以下:

>>> from inventory.models import Item
>>> from inventory.models import InStockBill
>>> inStock = InStockBill(InStockBillCode='20141101001',InStockDate='2014-11-01',Operator='張三',Amount=10)
>>> inStock.save()

  在沒有賦值給InStockBill屬性Item的狀況下咱們直接調用保存函數會報錯,數據不能正常提交到數據庫中。

>>> inStock.Item =  1

  咱們直接給inStock.Item 賦值1(Itemid=1的物料在咱們的例子中是前面保存進數據庫的「螺母」),也會報錯,雖然在數據庫裏,InStockBill表外鍵關係存儲的是關聯表的主鍵。須要inStock.Item賦值爲一個具體的Item模型才能正常的提交數據。Django在這裏已經把表映射爲對象了。注:本例中入庫單保存成功的同時,應該更新庫存表數據(入庫單將致使該物料庫存數量增長)後面咱們將在業務事物章節說明。

>>> item1 = Item.objects.get(ItemId=1)
>>> inStock.Item =item1
>>> inStock.save()
>>>

 

   這裏咱們會看見數據保存到數據庫中後,入庫時間變成了2014-10-31 16:00:00,這是由於settings.py時區設置爲:TIME_ZONE = 'America/Chicago'的緣故,把USE_TZ = True修改成便可USE_TZ = False:

# If you set this to False, Django will not use timezone-aware datetimes.
USE_TZ = False

5.4.4. 數據排序

  在你的 Django 應用中,你或許但願根據某字段的值對檢索結果排序,好比說,按字母順序。 那麼,使用 order_by() 這個方法就能夠搞定了。

>>> itms = Item.objects.all()
>>> print itms[0].ItemCode
003

>>> itms = Item.objects.order_by('ItemCode')
>>> print itms[0].ItemCode
000

  Django指定模型的缺省排序方式,在模型配置中配置

class Item(models.Model):
    ItemId = models.AutoField(primary_key=True)
    ItemCode = models.CharField(max_length=50)
    ItemName = models.CharField(max_length=50)

    class Meta: ordering = ['ItemCode']

5.4.5. 數據刪除

>>> itm2 = Item.objects.get(ItemId = 2)
>>> itm2.delete()
>>>

5.5. 小結

本章咱們經過一個簡單的實例模型例子來講Django模型如何建立、配置和訪問數據庫等。並經過Python環境演示了模型的裝載、訪問、查詢、保存、排序和刪除等操做。

下一章咱們將介紹Django是如何實現經過客戶端向服務端提交數據——表單。

相關文章
相關標籤/搜索