Django基礎(二)—— models

六:Models示例

Django自己提供了很是強大易使用的ORM組件,而且支持多種數據庫。python

配置鏈接數據文件mysql

在本身建立的project 目錄下編輯settings.pyweb

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',    # mysql 數據庫
        'NAME': 'dbname',             #確保此數據庫已存在
        'HOST':'',
        'PORT':'',
        'USER':'root',
        'PASSWORD':''
    }
}

 

假設下面的概念,字段關係:sql

1,一個做者有姓,名及email地址shell

2,出版商有名稱,地址,所在城市,省,國家,網站數據庫

3,書籍有書名和出版日期。它有一個或多個做者,只有一個出版商django

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

模型安裝

代碼完成後,就須要建立表了。python3.x

第一步,在Django項目中 激活這些模型。將上面的模型所在的app添加到配置文件的安裝應用列表中。session

# settings.py

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
   'app01',      # 本身所建立的Django項目名
)

 

按照模型的配置生成表結構

命令行模式:app

python manage.py makemigrations                    # 生成同步記錄

python manage.py migrate                                 # 開始同步數據庫

 

基本數據訪問

數據同步完成以後就能夠在命令行模式 使用 python manage.py shell 就能夠進入Django提供的高級python API

>>> from books.models import 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()            # 保存到數據庫
>>> 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: Publisher object>, <Publisher: Publisher object>]

若是須要一步建立與存儲到數據庫,就須要使用 objects.create() 方法

>>> p1 = Publisher.objects.create(name='Apress',
...     address='2855 Telegraph Avenue',
...     city='Berkeley', state_province='CA', country='U.S.A.',
...     website='http://www.apress.com/')        # 直接寫如數據庫
>>> 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/')
>>> publisher_list = Publisher.objects.all()
>>> publisher_list

 

__unicode__() 和 __str__()

當咱們打印整個publisher 列表時,咱們沒有獲得想要的信息,沒法把對象區分。

[<Publisher: Publisher object>, <Publisher: Publisher object>]

爲了解決這個問題,只須要爲publisher對象添加一個方法。這個方法告訴python 若是將對象以unicode的方式顯示出來。

def __str__(self):
        return self.name
# name爲須要顯示的字段名。能夠返回多個
# return "<%s %s>" %(self.first_name,self.last_name)

注:在python 2.x 裏面使用 __unicode_()  python3.x 裏面使用 __str__()

插入和更新數據

插入數據:

p = Publisher(name='Apress',
...         address='2855 Telegraph Ave.',
...         city='Berkeley',
...         state_province='CA',
...         country='U.S.A.',
...         website='http://www.apress.com/')

p.save()        # 這一步纔會插入數據庫

更新數據:

>>> p.name = 'Apress Publishing'    # 直接賦值,就是更改數據
>>> p.save()            # 保存

 

查找對象

>>> Publisher.objects.all()
[<Publisher: Apress>, <Publisher: O'Reilly>]
# 至關於SQL 語句
SELECT id, name, address, city, state_province, country, website
FROM books_publisher;

注意:Django 在選擇全部數據時並無使用 select * ,而是顯示列出了全部字段。由於 select * 會更慢,並且最重要的是列出全部字段遵循了python 界的一個信條:明言勝於暗示

數據過濾

filter() 方法進行數據過濾

>>> Publisher.objects.filter(name='Apress')
[<Publisher: Apress>]

能夠使用多個 filter() 來縮小範圍:

>>> Publisher.objects.filter(country="U.S.A.", state_province="CA")
[<Publisher: Apress>]

進行模糊匹配:

>>> Publisher.objects.filter(name__contains="press")
[<Publisher: Apress>]
# 在name和contains 之間有兩個下劃線。

# Django 使用雙下劃線來代表會進行一些操做。

轉爲原生的SQL:

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

 

獲取單個對象

使用get() 方法獲取單個對象

>>> Publisher.objects.get(name="Apress")
<Publisher: Apress>

這裏返回的是單個對象,而不是列表。因此若是結果是多個對象,就會致使拋出異常。

若是沒有查詢到結果也會拋出異常:

>>> Publisher.objects.get(name="Penguin")
Traceback (most recent call last):
    ...
DoesNotExist: Publisher matching query does not exist.

這個DoesNotExist 異常是 publisher 這個model 類的一個屬性,即publisher.DoesNotExist。在應用中能夠捕獲並處理這個異常。

try:
    p = Publisher.objects.get(name='Apress')
except Publisher.DoesNotExist:
    print "Apress isn't in the database yet."
else:
    print "Apress is in the database."

數據排序

使用order_by() 方法進行排序

>>> 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>]

儘管和靈活,可是每次都要用 order_by() 顯得有點囉嗦。大多數只會經過某些字段進行排序,這中狀況下Django 能夠指定模型的缺省排序方式:

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 Meta:
        ordering = ['name']
# 缺省排序字段

class Meta ,內嵌於Publisher這個類的定義中(若是class Publisher是頂格的,那麼class Meta 在它之下不要縮進4個空格)。能夠在任意一個模型中使用Meta類,來設置一些與特定模型相關的選擇。Meta 還能夠設置其餘選項。若是設置了這個選項,那麼觸發檢索時特地額外使用了 order_by() ,不然,當你使用Django的數據庫API去檢索時,Publisher對象的相關返回值默認都會按照name字段排序。

連鎖查詢

同時進行過濾和排序查詢

>>> Publisher.objects.filter(country="U.S.A.").order_by("-name")
[<Publisher: O'Reilly>, <Publisher: Apress>]

限制返回的數據

只顯示第一條數據

>>> Publisher.objects.order_by('name')[0]
<Publisher: Apress>

[ ] 內相似一個列表

好比取第一條和第二條

>>> Publisher.objects.order_by('name')[0:2]

可是不支持 負索引

更新多個對象

在插入和更新數據中,使用save()方法,這個方法會更新一行裏面的說有列。

>>> p = Publisher.objects.get(name='Apress')
>>> p.name = 'Apress Publishing'
>>> p.save()

#  原生的SQL語句:
SELECT id, name, address, city, state_province, country, website
FROM books_publisher
WHERE name = 'Apress';
 
UPDATE books_publisher SET
    name = 'Apress Publishing',
    address = '2855 Telegraph Ave.',
    city = 'Berkeley',
    state_province = 'CA',
    country = 'U.S.A.',
    website = 'http://www.apress.com'
WHERE id = 52;
#假設ID爲52

從原生的SQL來看save() 方法是更新了一行內的全部字段。

若是想只更新某一個字段

>>> Publisher.objects.filter(id=52).update(name='Apress Publishing')

轉爲的原生SQL

UPDATE books_publisher
SET name = 'Apress Publishing'
WHERE id = 52;

update()方法對任何結果集都有效。所以能夠同時更新多條記錄

>>> Publisher.objects.all().update(country='USA')
2

#update()方法會返回一個整數數值,表示受到影響的記錄條數。

刪除對象

使用delete()方法

>>> p = Publisher.objects.get(name="O'Reilly")
>>> p.delete()
>>> Publisher.objects.all()
[<Publisher: Apress Publishing>]

# 同也能夠刪除多條數據
>>> Publisher.objects.filter(country='USA').delete()
>>> Publisher.objects.all().delete()
>>> Publisher.objects.all()
[]

在刪除數據的時候要當心,一旦使用all()方法,全部的數據將會被刪除。

若是須要刪除部分的數據,就不須要調用all()方法。

>>> Publisher.objects.filter(country='USA').delete()
相關文章
相關標籤/搜索