Django -- 模型(資料庫層)

來源:互聯網
上載者:User

標籤: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 -- 模型(資料庫層)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.