Django 模型

發表於2016-03-19

模型是MVC架構中訪問資料的模組,Django的模型對各種資料庫提供了很好的支援。這裡以MySQL為例介紹Django的模型。

使用模型

啟用資料庫支援

在專案的 settings.py 檔案中找到 DATABASES 配置項, 根據資料庫配置資訊:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'test',
        'USER': 'testuser',
        'PASSWORD': '123456',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

Django的目錄結構包括Project和App兩層, 同一個Project下的不同App共享Project的資料庫連線。

settins.py中INSTALLED_APPS用來維護Project中的APP包括自定義APP和外掛APP.

必須在INSTALLED_APPS中新增APP的名稱字串,該APP才可以使用模型。

實現模型類

ORM (Object Relational Mapping,物件關係對映)將程式設計師定義的類對映為資料表。Django提供了優秀的ORM實現。

一般在model.py中定義相關模型,模型類需要繼承django.db.models.Model

類名代表資料表名,類中的欄位代表資料表中的欄位, 類的一個例項表示一條資料記錄。

將primary_key關鍵字引數置為True,即可新增主鍵約束。

在未指定primary_key的情況下,Django會預設建立一個id自增欄位作為主鍵。

示例:

from django.db import models

class Account(models.Model):
    account_name = models.CharField(max_length=20)
    account_id = models.IntegerField(primary_key=True)
    balance = models.DecimalField(max_digits=2, decimal_places=2)

同步資料庫

manage.py中提供了同步資料庫的命令,在專案目錄下依次執行命令

python manage.py makemigrations

python manage.py migrate

在修改資料庫結構後只需要重新同步資料庫即可。

終端互動歷史:

E:\workspace\Django\ThirdDjango>python manage.py makemigrations
Migrations for 'ModelDjango':
  0001_initial.py:
    - Create model Account

E:\workspace\Django\ThirdDjango>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, ModelDjango, contenttypes, auth, sessions
Running migrations:
  Rendering model states... DONE
  Applying ModelDjango.0001_initial... OK

注意在Django1.7及以後版本中python manage.py syncdb已被移除。

欄位

django.db.models模組中定義了大量標準欄位,常用的包括:

 CharField

SQL中的varchar型別,max_length關鍵字引數指定長度。

account_name = models.CharField(max_length=20)

IntegerField

整數字段

account_id = models.IntegerField(primary_key=True)

DecimalField

decimal型別,max_digits指定總位數, decimal_places指定小數位數

balance = models.DecimalField(max_digits=2, decimal_places=2)

AutoField

從1開始自增的整型欄位

id = models.AutoField()

DateTimeField

SQL中的datetime型別, 使用Python中的datetime.datetime型別表示

使用下面的建構函式構造一個datetime物件

datetime.datetime (year, month, day[ , hour[ , minute[ , second[ , microsecond[ , tzinfo]]]]])

關於Python的datetime模組詳情可以參考這篇部落格.

可以使用auto_now=True關鍵字引數使例項每次執行save()時該欄位自動儲存save時間,不允許手動賦值。

更多標準欄位請見Django Book:

中文版

英文原版

關係欄位

關係欄位用於儲存資料表之間的關係,包括ForeignKey, ManyToManyField等。

請參見Django Model 多表查詢

修改資料

在建立模型後Django提供了一系列API進行資料操作,取代原始SQL語句。

新增資料記錄

例項化模型類,用關鍵字引數對各列賦值,並呼叫物件的save()方法將物件寫入資料庫。

示例:

account_john = Account(account_name='john', accouunt_id='123', balance=0);
account_john.save()

save()方法沒有返回值,在顯式呼叫save()之前不會訪問資料庫.Account例項的欄位是可以直接訪問或修改的.

或者呼叫model_class.objects.create()

Account.objects.create(account_name='john', accouunt_id='123', balance=0)

或者使用:

Account.objects.get_or_create(account_name='john', accouunt_id='123', balance=0)

刪除資料記錄

呼叫資料記錄的delete()方法可以刪除資料記錄。

account.delete()

查詢資料

查詢資料使用QuerySet API。 QuerySet是惰性執行的,建立Query Set不會訪問資料庫,只有在訪問具體查詢結果的時候才會訪問資料庫。

獲取資料表的全部資料記錄:

Account.objects.all()

返回值可以進行切片,但不支援負索引。或者使用:

Account.objects.get(field_name=val)

示例:

Account.objects.get(account_name='john')

或者使用過濾器查詢多條記錄:

  • Account.objects.filter(accounnt_name=val)
    嚴格等於

  • Account.objects.filter(account_name__iexact=val)
    忽略大小寫

  • Account.objects.filter(account_name__contains=val)
    名稱中包含val

  • Account.objects.filter(account_name__icontains=val)
    忽略大小寫,包含

  • Account.objects.filter(account_name__regex=val)
    正規表示式

  • Account.objects.filter(account_name__iregex=val)
    正規表示式,忽略大小寫

與filter相反exclude用於返回不滿足條件的查詢結果。
Account.objects.exclude(account_name__contains=val)

filter與exclude可以進行鏈式查詢

Account.objects.exclude(account_name__contains='john').exlucde(balance=0)

對於查詢結果可以使用distinct()去重或者使用order_by(field)進行排序。

Account.objects.filter(account_name__regex=val).distinct()

Account.objects.filter(account_name__regex=val).oreder_by('balance')

使用reverse()方法可以反轉結果集中的元素順序,呼叫兩次將會恢復原順序。

從SQL 的角度,QuerySet和SELECT 語句等價,過濾器是像WHERE 和LIMIT 一樣的限制子句。

使用原生SQL

在模型查詢API不夠用的情況下,你可以使用原始的SQL語句。Django提供兩種方法使用原始SQL進行查詢。

一種是使用Model.objects.raw()方法,並進行原始查詢並返回模型例項:

Account.objects.filter('select * from account')

這種方法為延遲執行,如:

for a in Account.objects.filter('select account_name, balance from account'):
    print(a.account_name, a.account_id)

上述語句實際上執行了3次查詢,account_name在raw中被查詢, account_id在列印時被查詢。

另一種是完全避開模型層,直接執行自定義的SQL語句。

from django.db import connection

def my_account_sql(self):
    cursor = connection.cursor()

    cursor.execute("UPDATE account SET account_id = 1 WHERE baz = %s", [self.baz])

    cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
    row = cursor.fetchone()

    return row

與其它資料庫connection的用法非常類似。

編寫原始的SQL語句時,應該格外小心。 每次使用的時候,都要確保轉義了引數中任何使用者可以控制的字元,以防受到SQL隱碼攻擊。

相關文章