python學習筆記--Django入門三 Django 與數據庫的交互:數據建模


把數據存取邏輯、業務邏輯和表現邏輯組合在一起的概念有時被稱為軟件架構的 Model-View-Controller (MVC)模式。在這個模式中, Model 代表數據存取層,View 代表的是系統中選擇顯示什么和怎么顯示的部分,Controller 指的是系統中根據用戶輸入並視需要訪問模型,以決定使用哪個視圖的那部分。

由於 C 由框架自行處理,而 Django 里更關注的是模型(Model)、模板(Template)和視圖(Views),Django 也被稱為 MTV 框架 。在 MTV 開發模式中:

 

  M 代表模型(Model),即數據存取層。該層處理與數據相關的所有事務:如何存取、如何確認有效性、包含哪些行為以及數據之間的關系等。

  T 代表模板(Template),即表現層。該層處理與表現相關的決定:如何在頁面或其他類型文檔中進行顯示。

  V代表View,業務邏輯層。這一層包含訪問模型的邏輯和按照模板顯示。你可以認為它是模型和模板的橋梁。

數據庫配置

修改配置文件 settings.py 

DATABASE_ENGINE = ''
DATABASE_NAME = ''
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''

mysql多實例可以指定用戶

DATABASE_HOST = '/data/3306/mysql.sock'

高版本的Django連接數據庫配置有所不同,參考原版文檔:

 

 

如果你只是建造一個簡單的web站點,那么可能你只需要一個app就可以了。如果是復雜的象 電子商務之類的Web站點,你可能需要把這些功能划分成不同的app,以便以后重用。

系統對app有一個約定:如果你使用了Django的數據庫層(模型),你 必須創建一個django app。模型必須在這個app中存在。因此,為了開始建造 我們的模型,我們必須創建一個新的app。

轉到 mysite 項目目錄,執行下面的命令來創建一個新app叫做books:

python manage.py startapp books

在 mysite 目錄下創建了一個 books 的文件夾

books/
    __init__.py
    models.py
    views.py

創建你的第一個模型

在Django中使用該數據庫布局的第一步是將其表述為Python代碼。在通過“startapp”命令創建的“models.py”文件中,輸入如下代碼:

from django.db import models

class Publisher(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()

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()

 

每個模型相當於單個數據庫表,每個屬性也是這個表中的一個字段。 屬性名就是字段名,它的類型(例如 CharField )相當於數據庫的字段類型 (例如 varchar )。例如, Publisher 模塊等同於下面這張表(用PostgreSQL的 CREATE TABLE 語法描述):

CREATE TABLE "books_publisher" (
    "id" serial NOT NULL PRIMARY KEY,
    "name" varchar(30) NOT NULL,
    "address" varchar(50) NOT NULL,
    "city" varchar(60) NOT NULL,
    "state_province" varchar(30) NOT NULL,
    "country" varchar(50) NOT NULL,
    "website" varchar(200) NOT NULL
);

其中:

SERIAL是BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE的一個別名。

在整數列定義中,SERIAL DEFAULT VALUE是NOT NULL AUTO_INCREMENT UNIQUE的一個別名。

注:上面NOT NULL是不可為空,AUTO_INCREMENT是遞增,指定起始值為1用AUTO_INCREMENT=1語句,不指定默認也為1。

UNIQE是不可重復的意思,取值不能與已經存在的數據重復。

 

“每個數據庫表對應一個類”這條規則的例外情況是多對多關系。 在我們的范例模型中, Book 有一個 多對多字段 叫做 authors 。 該字段表明一本書籍有一個或多個作者,但 Book 數據庫表卻並沒有 authors 字段。 相反,Django創建了一個額外的表(多對多連接表)來處理書籍和作者之間的映射關系。

模型安裝

一個project包含很多個Django app以及對它們的配置。

技術上,project的作用是提供配置文件,比方說哪里定義數據庫連接信息, 安裝的app列表, TEMPLATE_DIRS,等等。 

一個app是一套Django功能的集合,通常包括模型和視圖,按Python的包結構的方式存在。

例如,Django本身內建有一些app,例如注釋系統和自動管理界面。 app的一個關鍵點是它們是很容易移植到其他project和被多個project復用。

 

完成這些代碼之后,現在讓我們來在數據庫中創建這些表。要完成該項工作,第一步是在 Django 項目中 激活 這些模型。將 books app 添加到配置文件的已 installed apps 列表中即可完成此步驟。

再次編輯 settings.py 文件, 找到 INSTALLED_APPS 設置。 INSTALLED_APPS 告訴 Django 項目哪些 app 處於激活狀態。缺省情況下如下所示:

MIDDLEWARE_CLASSES = (
#    'django.middleware.common.CommonMiddleware',
#    'django.contrib.sessions.middleware.SessionMiddleware',
#    'django.contrib.auth.middleware.AuthenticationMiddleware',
#    'django.middleware.doc.XViewMiddleware',
)

TEMPLATE_CONTEXT_PROCESSORS = ()
#...

INSTALLED_APPS = (
    #'django.contrib.auth',
    #'django.contrib.contenttypes',
    #'django.contrib.sessions',
    #'django.contrib.sites',
    'mysite.books',
)

現在我們可以創建數據庫表了。首先,用下面的命令對校驗模型的有效性:

python manage.py validate

 檢查試會報錯:

TypeError: __init__() got an unexpected keyword argument ‘maxlength’

應該是以前的版本是應該用maxlength,但是新版本里面使用max_length

在vim中替換    :%s/maxlength/max_length/g

然后再次報錯:

Error: One or more models did not validate:
books.author: "headshot": To use ImageFields, you need to install the Python Imaging Library. Get it at http://www.pythonware.com/products/pil/ .

那就開始安裝這個庫:

pip install PIL

DEPRECATION: Python 2.6 is no longer supported by the Python core team, please upgrade your Python. A future version of pip will drop support for Python 2.6
Collecting PIL
Could not find a version that satisfies the requirement PIL (from versions: )
No matching distribution found for PIL

只能升級python了

 升級到了2.7版本,還是報錯,干脆升級到3.X看看情況:使用souhu的源還是比較快

wget http://mirrors.sohu.com/python/3.3.3/Python-3.3.3.tar.bz2

 在編譯前先在/usr/local建一個文件夾python3.3 .3(作為Python的安裝路徑,以免覆蓋老的版本)

 

mkdir -p /usr/local/python-3.3.3

 

在解壓縮后的目錄下編譯安裝

./configure --prefix=/usr/local/python-3.3.3
make && make install

將原來/usr/bin/python鏈接改為別的名字

mv /usr/bin/python /usr/bin/python_old

再建立新版本python的鏈接

ln -s /usr/local/python3.3.3/bin/python3 /usr/bin/python

安裝好之后,需要重新安裝setuptools , pip ,MySQLdb, Django

但是經歷了好多,發現對這些的支持都有問題,索性,換一個方法來做:

還是用系統自帶的python2.6.6 , 其他的插件,不用pip來安裝,直接下載先來自己安裝

Imaging-1.1.7

python setup.py install  然后就搞定了

繼續問題前的操作

python manage.py validate

看到 errors found 消息,一切正常。繼續:

運行下面的命令來生成 CREATE TABLE 語句:

python manage.py sqlall books
BEGIN;
CREATE TABLE `books_publisher` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `name` varchar(30) NOT NULL,
    `address` varchar(50) NOT NULL,
    `city` varchar(60) NOT NULL,
    `state_province` varchar(30) NOT NULL,
    `country` varchar(50) NOT NULL,
    `website` varchar(200) NOT NULL
)
;
CREATE TABLE `books_author` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `salutation` varchar(10) NOT NULL,
    `first_name` varchar(30) NOT NULL,
    `last_name` varchar(40) NOT NULL,
    `email` varchar(75) NOT NULL,
    `headshot` varchar(100) NOT NULL
)
;
CREATE TABLE `books_book` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `title` varchar(100) NOT NULL,
    `publisher_id` integer NOT NULL,
    `publication_date` date NOT NULL
)
;
ALTER TABLE `books_book` ADD CONSTRAINT `publisher_id_refs_id_4cdc253fc5b274bb` FOREIGN KEY (`publisher_id`) REFERENCES `books_publisher` (`id`);
CREATE TABLE `books_book_authors` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `book_id` integer NOT NULL,
    `author_id` integer NOT NULL,
    UNIQUE (`book_id`, `author_id`)
)
;
ALTER TABLE `books_book_authors` ADD CONSTRAINT `book_id_refs_id_5565ddfcfbcf262` FOREIGN KEY (`book_id`) REFERENCES `books_book` (`id`);
ALTER TABLE `books_book_authors` ADD CONSTRAINT `author_id_refs_id_1f0e145e09e7e386` FOREIGN KEY (`author_id`) REFERENCES `books_author` (`id`);
CREATE INDEX `books_book_publisher_id` ON `books_book` (`publisher_id`);
COMMIT;

sqlall 命令並沒有在數據庫中真正創建數據表,只是把SQL語句段打印出來。運行 syncdb 命令

python manage.py syncdb
Creating table books_publisher
Creating table books_book
Creating table books_author
Installing index for books.Book model

成功創建了表

基本數據訪問

添加一個方法 __unicode__() 到 Publisher 對象。 __unicode__() 方法告訴Python要怎樣把對象unicode的方式顯示出來.

普通的python字符串是經過編碼的,意思就是它們使用了某種編碼方式(如ASCII,ISO-8859-1或者UTF-8)來編碼。

但是Unicode對象並沒有編碼。它們使用Unicode,一個一致的,通用的字符編碼集。 當你在Python中處理Unicode對象的時候,你可以直接將它們混合使用和互相匹配而不必去考慮編碼細節。

from django.db import models
class Publisher(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()

    **def __unicode__(self):**
        **return self.name**

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField()

    **def __unicode__(self):**
        **return u'%s %s' % (self.first_name, self.last_name)**

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()

    **def __unicode__(self):**
        **return self.title**
 
>>> from books.models import Publisher
>>> p1 = Publisher(name='Addison-Wesley', address='75 Arlington Street',
...     city='Boston', state_province='MA', country='U.S.A.',
...     website='http://www.apress.com/')
>>> p1.save()
>>> p2 = Publisher(name="O'Reilly", address='10 Fawcett St.',
...     city='Cambridge', state_province='MA', country='U.S.A.',
...     website='http://www.oreilly.com/')
>>> p2.save()
>>> publisher_list = Publisher.objects.all()
>>> publisher_list

[<Publisher: Addison-Wesley>, <Publisher: O'Reilly>]
 

所有的數據庫查找都遵循一個通用模式:調用模型的管理器來查找數據。

數據過濾

如果想要獲得數據的一個子集,我們可以使用 filter() 方法:SQL缺省的 = 操作符是精確匹配的

Publisher.objects.filter(country="U.S.A.", state_province="CA")

這個 __contains 部分會被Django轉換成 LIKE SQL語句

Publisher.objects.filter(name__contains="press")

等同於:

SELECT
    id, name, address, city, state_province, country, website
FROM book_publisher
WHERE name LIKE '%press%';

獲取單個對象

使用 get() 方法:

Publisher.objects.get(name="Apress Publishing")

數據排序

用 order_by() 來 排列返回的數據:

Publisher.objects.order_by("name")

還可以指定逆向排序,在前面加一個減號 - 前綴:

Publisher.objects.order_by("-name")

每次都要用 order_by() 顯得有點啰嗦。 大多數時間你通常只會對某些 字段進行排序。在這種情況下,Django讓你可以指定模型的缺省排序方式:

class Publisher(models.Model):
    name = models.CharField(maxlength=30)
    address = models.CharField(maxlength=50)
    city = models.CharField(maxlength=60)
    state_province = models.CharField(maxlength=30)
    country = models.CharField(maxlength=50)
    website = models.URLField()

    def __str__(self):
        return self.name

    class Meta:
        ordering = ["name"]

這個 ordering ["name"] 告訴Django如果沒有顯示提供 order_by() , 就缺省按名稱排序。

 

可以同時做這 過濾和排序

Publisher.objects.filter(country="U.S.A.").order_by("-name")

限制返回的數據

只想顯示第一個

Publisher.objects.all()[0]

刪除對象

調用對象的 delete() 方法:

p = Publisher.objects.get(name="Addison-Wesley")
p.delete()

后邊的數據庫操作比較繁瑣,就等用的時候再學習更新吧

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM