標籤:django 模型 資料庫層
web應用中,主觀邏輯(視圖處理)經常牽涉與資料庫的互動。資料庫驅動網站在後台串連資料庫,從中取資料,然後甩漂亮介面展現在web端。許多複雜的網站都提供以上兩種功能的結合(如Amazon.com),而Python天生具備簡單強大的資料庫查詢執行方法,很適合開發這類資料庫驅動網站。
他就是下面介紹的Django資料庫層!
【 硬 編 碼 鏈 接 數 據 庫 】
cat ~/HelloWorld/HelloWorld/view.py
from django.shortcuts import render_to_responseimport MySQLdbdef book_list(request): db = MySQLdb.connect(user=‘me‘, db=‘mydb‘, passwd=‘secret‘, host=‘localhost‘) cursor = db.cursor() cursor.execute(‘SELECT name FROM books ORDER BY name‘) names = [row[0] for row in cursor.fetchall()] db.close()return render_to_response(‘book_list.html‘, {‘names‘: names})
弊端:此方法雖可用,但是我們將參數配置直接寫入程式碼到視圖函數,顯然犯了前兩節相同的錯誤;如果我們改一個參數、改一種資料庫、換個執行語句等等,都會引起大範圍的改動。
那我們能不能像上節那樣建立模板,其實django提供了更簡單直接的方式:資料庫API
===============================================================================================
MVC架構模式、MTV 開發模式
Django 設計遵循松耦合原則,修改某部分不影響其他部分。視圖函數中通過了模板系統將商務邏輯和表現邏輯分隔,資料庫層也應如此。
MVC 架構模式:即資料存取邏輯(model)、表現邏輯(view)、商務邏輯(controller)的組合
其中 C 由架構自行處理,django更關注的是模型(model)、模板(template)、視圖(views),也被稱MTV架構
M:資料存取,處理與資料相關所有事務;
T:表現層,處理與表現相關的決定,比如頁面如何顯示;
V:視圖,處理存模數型和調模數板的邏輯,可看做模型與模板的橋樑。
注: django認為視圖用來展現資料,控制器是如何展示;其他架構認為控制器用來展現資料,視圖決定如何展現。
================================================================================================
上面所說的資料庫API,其實就是更改django設定檔,通過設定檔的介面進資料庫。
| 資料庫 |
DATABASE_ENGINE |
適配器 |
| PostgreSQL |
postgresql |
http://www.djangoproject.com/r/python-pgsql/1/ |
| PostgreSQL |
postgresql_psycopg2 |
http://www.djangoproject.com/r/python-pgsql/ |
| MySQL |
mysql |
http://www.djangoproject.com/r/python-mysql/ |
| SQLite |
sqlite3 |
http://www.djangoproject.com/r/python-sqlite/ |
| Oracle |
oracle |
http://www.djangoproject.com/r/python-oracle/ |
vim ~/HelloWorld/HelloWorld/settings.pyDATABASES = { ‘default‘: { ‘ENGINE‘: ‘django.db.backends.mysql‘, ‘NAME‘: ‘django‘, ‘USER‘: ‘django‘, ‘PASSWORD‘: ‘django123‘, ‘HOST‘:‘localhost‘, ‘PORT‘:‘3306‘,}}
之後去資料庫建一個django庫,並給django使用者賦值。然後測試一下(沒有報錯資訊即配置成功,並能連結到mysql的django庫了,關於django報錯資訊,請參考下一節):
啟動shell介面:python manage.py shell
>>> from django.db import connection
>>> cursor = connection.cursor()
【應用程式app 與 模型model.py】
第 一 個 app
Django規定:如果使用了django資料庫層(或模型),必須要建立django app,把模型放在裡面;應用程式app是項目project組成部分。
python manage.py startapp mysql_django #建立mysql_django app
650) this.width=650;" src="http://s2.51cto.com/wyfs02/M01/8B/E8/wKioL1hcETyAMEeSAAAWixnqf4s271.png" title="1.png" alt="wKioL1hcETyAMEeSAAAWixnqf4s271.png" />
建立好app,將app加入到HelloWorld project中
vim ~/HelloWorld/HelloWorld/settings.pyINSTALLED_APPS = [‘django.contrib.admin‘,‘django.contrib.auth‘,‘django.contrib.contenttypes‘,‘django.contrib.sessions‘,‘django.contrib.messages‘,‘django.contrib.staticfiles‘,** ‘mysql_django‘, #逗號結尾,也可用點文法 HelloWorld.mysql_django]
第 一 個 模 型
其實django模型就是以python代碼錶述資料庫中表結構
vim ~/HelloWorld/mysql_django/models.pyfrom django.db import modelsclass Publisher(models.Model): #CREATE TABLE "books_publisher"("id" serial NOT NULL PRIMARY KEY, name = models.CharField(max_length=30) #"name" varchar(30) NOT NULL, address = models.CharField(max_length=50) #"address" varchar(50) NOT NULL, city = models.CharField(max_length=60) #"city" varchar(60) NOT NULL, state_province = models.CharField(max_length=30) #"state_province" varchar(30) NOT NULL, country = models.CharField(max_length=50) #"country" varchar(50) NOT NULL, website = models.URLField() #"website" varchar(200) NOT NULL ); class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField() class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField()
代碼解讀:
1、首先每個資料模型都是django.db.models.Model的子類,父類Model包含所有與資料庫互動的必要方法;
2、每個模型相當於資料庫表,每個屬性即欄位,類型(CharField)相當於欄位類型(varchar)
3、Publisher舉例,python文法即等於右邊的資料庫文法。
4、定義了出版商、作者、書籍的一些內容。
當完成以上模型建表後,並將其app加入到了項目,接下來就開始執行建表了
a、檢查語法錯誤(django1.9.0版本以下用 python manage.py validate)
python manage.py check
b、產生資料庫遷移檔案(在app下的migrations下產生0001檔案,更改後執行,產生0002....遷移檔案)
python manage.py makemigrations mysql_django
c、同步資料庫(老版本用python manage.py syncdb,即把遷移檔案轉換文法同步資料庫[庫名app名_類名])
python manage.py migrate
d、轉換成 SQL 語言(老版本 python manage.py sqlall mysql_django,查看轉換後的mysql文法)
python manage.py sqlmigrate mysql_django 0001
【Python 與 數 據 庫 API】
進入:python manage.py shell
>>> from mysql_django.models import Publisher #匯入Publisher模型類
>>> p1 = Publisher(name=‘Apress‘, address=‘2855 Telegraph Avenue‘,
... city=‘Berkeley‘, state_province=‘CA‘, country=‘U.S.A.‘,
... website=‘http://www.apress.com/‘)
>>> p1.save() #調用了save()方法,才能真正將p1插入資料庫
>>> p2 = Publisher.objects.create(name="O‘Reilly",
... address=‘10 Fawcett St.‘, city=‘Cambridge‘,
... state_province=‘MA‘, country=‘U.S.A.‘,
... website=‘http://www.oreilly.com/‘) #objects.create()方法可直接將資料插入資料庫
>>> publisher_list = Publisher.objects.all() #從資料庫取出出版商資訊==select
>>> publisher_list
[<Publisher: Publisher object>, <Publisher: Publisher object>]
插入兩個資料後,講道理Publisher.objects.all()方法會取出Publisher類的對象,但是卻沒有得到有用資訊;
解決此問題:要為Publisher對象添加一個__unicode__()方法,他告訴python將對象以unicode方式顯示,如下:
vim ~/HelloWorld/mysql_django/models.pyfrom django.db import modelsclass Publisher(models.Model): name = models.CharField(max_length=30) ...................... website = models.URLField()** def __unicode__(self):** return self.nameclass Author(models.Model): .........................** def __unicode__(self):** return u‘%s %s‘ % (self.first_name, self.last_name)**class Book(models.Model): .........................** def __unicode__(self):** return self.title
============================================================================================
unicode對象 是能處理上百萬不同類的字串的python字串。普通的python字串是經過編碼的,穿插調用的話就會出現常見的???等亂七八糟的字元,這就是編碼的問題;而unicode對象沒有編碼,使用它可以不用考慮編碼的問題。所以請確保每個模型都定義了__unicode__()方法。
關於unicode:http://www.joelonsoftware.com/articles/Unicode.html
再次進入shell解譯器內,實驗:>>> publisher_list
[<Publisher: Apress>, <Publisher: O‘Reilly>]
============================================================================================
1、資料查看、過濾操作:
>>> Publisher.objects.filter(name=‘Apress‘)
[<Publisher: Apress>] #filter == where name=‘Apress‘
>>> Publisher.objects.filter(country="U.S.A.", state_province="CA")
[<Publisher: Apress>] #逗號轉換成了 and
>>> Publisher.objects.filter(name__contains="press")
[<Publisher: Apress>] #__contains = where name LIKE ‘%press%‘;
>>> Publisher.objects.get(name="Apress")
<Publisher: Apress> #get()方法擷取單個對象,filter()函數返回一個記錄集(列表)
(icontains[大小寫無關的LIKE]、startwith/endswith、range[BETWEEN])
2、資料排序操作:
>>> Publisher.objects.order_by("name")
[<Publisher: Apress>, <Publisher: O‘Reilly>] #按字母排序
>>> Publisher.objects.order_by("state_province", "address")
[<Publisher: Apress>, <Publisher: O‘Reilly>] #第一個欄位相同,按第二個排序
>>> Publisher.objects.order_by("-name")
[<Publisher: O‘Reilly>, <Publisher: Apress>] #-號,表示逆向排序
vim ~/HelloWorld/mysql_django/models.py class Publisher(models.Model): def __unicode__(self): return self.name** class Meta: ** ordering = [‘name‘] #Meta類,預設會以name欄位進行排序
3、連鎖查詢:
>>> Publisher.objects.filter(country="U.S.A.").order_by("-name")
[<Publisher: O‘Reilly>, <Publisher: Apress>] #檢索country="U.S.A."降序排列
>>> Publisher.objects.order_by(‘name‘)[0:2] #取資料的特定子集=offset 0 limit 2,查詢語句也可以加
>>> Publisher.objects.order_by(‘name‘)[0] #[0]=limit 1;不支援負索引[-1],但可用降序[0]實現
<Publisher: Apress>
4、增加更改操作:(name、save、id、update)
添加資料:>>> p3 = ....name=‘Apress‘ ...
擷取資料:>>> p2 = Publisher.objects.get(name="Apress")
更改資料:>>> p2.name = ‘Apress Publishing‘
儲存資料:>>> p2.save() #他會update此id全部欄位,不只是name欄位;也有輕量級更改的方法。
看主鍵id:>>> p2.id #我們可根據get到的資料查id,也可直接進資料庫查
更改資料:>>> Publisher.objects.filter(id=1).update(name=‘Apress Publishing‘)
批量更改:>>> Publisher.objects.all().update(country=‘USA‘) #返回數值即更改的條數
5、刪除命令操作:
擷取資料:>>> p = Publisher.objects.get(name="O‘Reilly") #先得到資料再刪除
刪除資料:>>> p.delete()
直接刪除:>>> Publisher.objects.filter(country=‘USA‘).delete() #刪除所有country=‘USA‘的
刪除全部:>>> Publisher.objects.all().delete() #不加all()方法刪除不了
查看資料:>>> Publisher.objects.all()
當然,以上的操作都是直接在shell解譯器中操作,我們也可以寫到視圖函數中,頁面化查看。
-------------------------------------------------------------------------------------------------
本文出自 “北冰--Q” 部落格,請務必保留此出處http://beibing.blog.51cto.com/10693373/1885340
Django -- 模型(資料庫層)