Django model 層之Models與Mysql數據庫小結


Django model 層之ModelsMysql數據庫小結

by:授客 QQ1033553122

 

測試環境:

Python版本:python-3.4.0.amd64

下載地址:https://www.python.org/downloads/release/python-340/

 

 

Win7 64位

 

Django  1.11.4

下載地址:https://www.djangoproject.com/download/

 

 

MySQL數據庫為例,假設項目目錄結構如下:

mysite/

myapp/

    __init__.py

admin.py

apps.py

migrations/

    __init__.py

models.py

tests.py

views.py

    manage.py
    mysite/
        __init__.py
        settings.py
        urls.py
        wsgi.py

 

 

配置數據庫信息

打開項目根目錄下,與項目同名的目錄,編輯settings.py(例中mysite/mysite/settings.py文件),

找到以下代碼
DATABASES = {
'default': {
……略
}
}
 
修改為以下內容:
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'testdb',
        'USER': 'testacc',
        'PASSWORD': 'test1234',
        'HOST': '192.168.1.102',
        'PORT': '3306',
        'OPTION':{
            'init_command': 'SET default_storage_engine=INNODB'
        }
    }
}

 

說明:

ENGINE:默認為空。可選值:

'django.db.backends.postgresql'

'django.db.backends.mysql'

'django.db.backends.sqlite3'

'django.db.backends.oracle'

 

NAME:數據庫名字。

如果使用SQLite,數據庫文件將存放在電腦上,這種情況下,NAME應該為絕對路徑,包含數據庫文件的文件名。默認值如下,把數據庫文件存放在項目根目錄下。

DATABASES = {

    'default': {

        'ENGINE': 'django.db.backends.sqlite3',

        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),

    }

}

 

如果不使用SQLite,需要設置額外參數如USER, PASSWORDHOST, PORT

 

另外,確保提供的USER具備“create database”權限。

 

USER: 數據庫用戶名,默認為''

 

PASSWORD:連接數據庫用戶密碼,默認為''

 

HOST: 數據庫服務器主機地址,默認為'',代表localhost。支持tcp socket除外的其它socket連接方式,更多詳情請查看官方文檔。

 

PORT:數據庫訪問端口,默認為'',代表默認端口。

 

AUTOCOMMIT: 自動提交事務。默認為True。設置為False,則禁用Django 事務管理,采用自己實現的事務管理。

 

更多選項設置,請參考官方文檔。

 

參考鏈接:

https://docs.djangoproject.com/en/1.11/ref/settings/#databases

 

建立表

編輯應用目錄下的models.py文件(例中為 mysite/myapp/models.py)

from django.db import models
 
# Create your models here.
class Person(models.Model):
   first_name = models.CharField(max_length=30)
   last_name = models.CharField(max_length=30)

 

新增以上帶背景色代碼

first_name和last_name為model的field。每個field映射到一個數據庫列。

 

以上Person model將創建如下表:

CREATE TABLE myapp_person (

    "id" serial NOT NULL PRIMARY KEY,

    "first_name" varchar(30) NOT NULL,

"last_name" varchar(30) NOT NULL);

 

注意:

1、如上,表名命名方式為應用名稱_轉為小寫的model名稱,我們可以通過Meta屬性實現表名自定義,如下:

 

CREATE TABLE myapp_person (

    "id" serial NOT NULL PRIMARY KEY,

    "first_name" varchar(30) NOT NULL,

"last_name" varchar(30) NOT NULL);

 

class Meta:

    db_table = 'tb_person'#數據庫中創建的表名稱即為 tb_person

verbose_name = '用戶表'#表名稱 #在admin站點中顯示的名稱

verbose_name_plural = verbose_name#顯示的復數名稱

 

 

2、自動為數據庫增加 id 自增主鍵列。因為,默認的,Django為每個模塊設置一個field:

id = models.AutoField(primary_key=True)

如果想自己指定一個自定義的主鍵列,則必須按上述設置,顯示指定字段名稱。總之,不管是默認設置還是顯示設置,必須有一個自增主鍵列。

參考鏈接:

https://docs.djangoproject.com/en/1.11/topics/db/models/#automatic-primary-key-fields

 

 

 
class Book(models.Model):
    book_name = models.CharField(max_length=30)
    borrower = models.ForeignKey(Person, to_field='id', on_delete=models.CASCADE)
 
說明:mysql中,生成的外鍵列名稱,會自動命名為:field_id,如上borrower field對應的mysql列為borrower_id
 
class Musician(models.Model):
    auto_id = models.IntegerField(primary_key=True)
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    instrument = models.CharField(max_length=100)
    last_update = models.DateField(auto_now=True, auto_now_add=True)
 
class Album(models.Model):
    artist = models.ForeignKey(Musician, to_field='auto_id', on_delete=models.PROTECT)
    name = models.CharField(max_length=100)
    release_date = models.DateField()
    num_stars = models.IntegerField()

 

 

Field 類型

 

AutoField

IntegerField,根據可獲取的ID列值,自增

 

參數:verbose_name,個人推斷,所有Field類型應該都有該參數,用於設置字段名稱

 

BigAutoField

64位整型,類似AutoField,不同之處在於它可接收更大范圍的數值:1 到9223372036854775807.

Django 1.10新增。

 

BigIntegerField

64位整型,類似IntegerField。不同之處在於它可接納更大范圍的數值:-9223372036854775808 到9223372036854775807。該field對應的默認組建:TextInput

 

BinaryField

用於存儲原始二進制數據,僅支持字節。

 

BooleanField

true/false field.該field對應的默認表單組件:CheckboxInput。

如果需要接收null值,則使用NullBooleanField替代BooleanField。

如果未定義Field.default,那么BooleanField field默認值為None。

 

CharField

字符串類型。用於存儲一定范圍大小的字符串。針對大量文本,使用TextField。該field的默認組建為:TextInput

CharField有個額外的必填參數。CharField.max_length。設置可接納的最大字符數。

 

DateField

日期類型。代表Python datetime.date實例。

class DateField(auto_now=False, auto_now_add=False, **options)[source]

可選參數:

DateField.auto_now

每次存儲對象(僅針對調用save方法)時,自動設置該field的值為當前日期

 

注意:實踐發現,調用Module_name.objects.Create()方法創建對象,auto_now()也起作用

 

DateField.auto_now_add

第一次創建對象時,自動設置field值為當前日期,所以,即便顯示為該字段提供了值,也會自動忽視顯示設定的值。

對於DateField:default=date.today - datetime.date.today()

對於DateTimeField: default=timezone.now - django.utils.timezone.now()

 

該field對應的默認表單組件為:TextInput。

 

注意:auto_now_add和auto_now兩個參數不能同時使用。

 

 

TimeField

以python datetime.time實例表示的時間

 

可選參數:

DateField.auto_now

每次存儲對象(僅針對調用save方法)時,自動設置該field的值為當前日期

 

DateField.auto_now_add

第一次創建對象時,自動設置field值為當前日期,所以,即便顯示為該字段提供了值,也會自動忽視顯示設定的值。

對於DateField:default=date.today - datetime.date.today()

對於DateTimeField: default=timezone.now - django.utils.timezone.now()

 

該field對應的默認表單組件為:TextInput。

 

 

DateTimeField

以python datetime.datetime實例表示的日期時間。

可選參數:

DateField.auto_now

每次存儲對象(僅針對調用save方法)時,自動設置該field的值為當前日期時間

 

DateField.auto_now_add

第一次創建對象時,自動設置field值為當前日期時間,所以,即便顯示為該字段提供了值,也會自動忽視顯示

該field對應的默認表單組件為:TextInput。

 

DateTimeField字段的值,如果要保存為當前時間,可以通過timezone.now()快速獲取當前時間進行賦值

>>> from django.utils import timezone

>>> update_time = timezone.now()

>>>user = User(username='test1', password='passwd123', email='email@163.com', update_time=update_time)

>>> user.save()

 

DecimalField

用Python Decimal實例表示的固定精度的數字。有兩個必填參數:

 

DecimalField.max_digits

表示允許的最大值。必須大於等於decimal_spaces

 

DecimalField.decimal_places

設置精度位數。

 

比如field存儲最大值不超過999,2位小數,設置如下:

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

該field對應的默認表單組件:當設置localize為False,則對應NumberInput,否則TextInput。

DurationField

存儲以python timedelat表示的一段時間

 

EmailField

一個CharField,校驗值是否是合法的email地址。使用EmailValidator校驗輸入值。

FileField

file-upload field。

注意:主鍵列不支持該類型。

更多詳情參考官方文檔。

 

FilePathField

一個CharField,可取值限制於系統上某個目錄中的文件名

更多詳情參考官方文檔。

FloatField

python float實例表示的浮點數。

該field對應的默認表單組件:當設置localize為False,則對應NumberInput,否則TextInput。

 

ImageField

繼承了FileField的所有屬性和方法。校驗上載對象是否是合法的圖片。

更多詳情參考官方文檔。

IntegerField

整數。值從-2147483648 到2147483647,支持所有數據庫。

該field對應的默認表單組件:當設置localize為False,則對應NumberInput,否則TextInput。

GenericIPAddressField

字符串格式(例如:192.0.2.30 or 2a02:42fe::4)表達的IPv4或IPv6地址,,針對IPv6,所有字符都會轉為小寫。

該field對應的默認表單組件:TextInput。

 

更多詳情參考官方文檔。

 

NullBooleanField

類似BooleanField,不同之處在於運行NULL值。等同BooleanField(...,null=True)。

該field對應的默認表單組件為NullBooleanSelect。

 

PositiveIntegerField

類似IntergerField,不同在於只接受正數,或者0.可取值范圍:0 到2147483647

 

PositiveSmallIntegerField

類似PositiveIntegerField,可取值范圍: 0 到 32767

 

SlugField

更多詳情參考官方文檔。

 

SmallIntegerField

類似IntegerField,取值范圍:-32768 到 32767

 

TextField

大文本field。如果指定max_length屬性,將作用於組件,但是不會是在數據庫、model層起作用(If you specify a max_length attribute, it will be reflected in the Textarea widget of the auto-generated form field. However it is not enforced at the model or database level)。

該field對應的默認表單組件為:Textarea。

 

URLField

針對URL的CharField。可選參數:max_length,設置最大長度。默認200.

field對應的默認表單組件為:TextInput

 

UUIDField

存儲全球唯一標識(universally unique identifier)。使用Python的UUID類。

對於主鍵AutoField來說,UUIDFeild是個很好的選擇。但是數據庫不會生成UUID,所以推薦使用default,如下:

import uuidfrom django.db import models

 

class MyUUIDModel(models.Model):

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

# other fields

 

 

參考鏈接:

https://docs.djangoproject.com/en/1.11/ref/models/fields/#model-field-types

 

 

 

常用Field option

null

如果設置null=True,保存數據到數據庫時,把“空值”存儲為NULL。默認null=False。

 

blank

如果設置blank=True, 允許Field值為空,字符型字段CharField和TextField是用空字符串來存儲空值的。默認False

 

注意:

blank 是針對表單的,如果 blank=True,表示你的表單填寫該字段的時候可以不填。

null 是針對數據庫而言,如果 null=True, 表示數據庫的該字段可以為空,那么在新建一個model對象的時候是不會報錯的!!

 

choice

一個由多個2元組,組成的可迭代對象(如tuple、list)。

 

如果設置了該選項值,那么默認的表單組件將變為一個select box,而不是標准是text field,且將被限制從給定choice中選擇choice。

choice 列表,形如以下:

YEAR_IN_SCHOOL_CHOICES = (

    ('FR', 'Freshman'),

    ('SO', 'Sophomore'),

    ('JR', 'Junior'),

    ('SR', 'Senior'),

    ('GR', 'Graduate'),)

 

每個元組中第一個元素,將被存儲在數據庫中,第二個元素用於默認表單組件展示

 

例:

from django.db import models

class Person(models.Model):

    SHIRT_SIZES = (

        ('S', 'Small'),

        ('M', 'Medium'),

        ('L', 'Large'),

    )

    name = models.CharField(max_length=60)

    shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)

 

>>> p = Person(name="Fred Flintstone", shirt_size="L")

>>> p.save()

>>> p.shirt_size

'L'

>>> p.get_shirt_size_display()

'Large'

 

default

設置field的默認值。可以是可調用對象,也可以是某個值。如果是可調用對象,每次創建對象,都會被調用

 

help_text

同表單組件一起展示的幫助說明

 

primary_key

如果設置primary_key=True,那么該field將是model的主鍵

 

主鍵Field只讀。如果修改某個已存在對象,主鍵列的值,並保存該對象,會在舊對象的基礎上,重新構建一個對象。

 

例:

from django.db import models

 

class Fruit(models.Model):

name = models.CharField(max_length=100, primary_key=True)

 

>>> fruit = Fruit.objects.create(name='Apple')

>>> fruit.name = 'Pear'

>>> fruit.save()

>>> Fruit.objects.values_list('name', flat=True)

<QuerySet ['Apple', 'Pear']>

 

unique

如果設置unique=True,則該field不允許有重復值。

 

參考鏈接:

https://docs.djangoproject.com/en/1.11/topics/db/models/#field-options

 

關聯關系

 

外鍵關聯

假設artist model對應mysql表為 myapp_album, Musician model對應的mysql表為Musician表為myapp_musician,則以下field定義,會使兩個mysql表建立外鍵關聯關系。myapp_album.artist列引用mapp_musician.auto_id字段的值,即mapp_musician.auto_id為myapp_album表的外鍵。

 

class Album(models.Model):

    artist = models.ForeignKey(Musician, to_field='auto_id', on_delete=models.PROTECT)

 

為方便理解,如上,暫時把Album、Musician Model稱之為表,對應Model對象稱之為表記錄,存在外鍵關聯的兩個表,分別稱之為參照表(如上的Album),被參照表(如上的Musician)

 

假設Musician代碼位於 Album代碼之前,那么執行以上代碼時將報錯,因為那會還沒有定義Musician,如果不調整代碼順序,即定義表的先后順序,那怎么辦呢?

解決方案:把關聯表寫成字符串形式,如下:

 

class Album(models.Model):

    artist = models.ForeignKey('Musician', to_field='auto_id', on_delete=models.PROTECT)

 

自身關聯

假設有表appame_resource,結構如下,其中parent的值如果不為NULL則為某條記錄的id值

id name parent

1  xxx1  NULL

2  xxx2   1

 

這種情況則需要進行自身表關聯設計,model設計如下:

class Resource(models.Model):

    id = models.AutoField(primary_key=True, verbose_name='資源ID')

    parent = models.ForeignKey('self', to_field='id', null=True, blank=True, on_delete=models.CASCADE)

    name = models.CharField(max_length=20, verbose_name='資源名稱')

 

null參數值說明:該值默認為False,設置為True則表示允許字段為null,空值將被存儲為NULL

blank參數值說明:該值默認為False,設置為True則表示允許字段為空值

 

on_delete參數值說明:

2.0版本,該參數值必填,更早之前的版本則默認為CASCADE。

可選值:

 

CASCADE

級聯刪除。模擬sql約束 ON DELETE CASCADE。刪除被參照表的某條表記錄,同時級聯刪除參照表中,同待刪除記錄存在外鍵關聯關系的記錄。

 

PROTECT

刪除被參照表中的某條表記錄,如果參照表中,存在與該記錄有外鍵關系的記錄,則不讓刪除。

 

SET_NULL

刪除被參照表的某條表記錄,設置參照表中,同待刪除記錄存在外鍵關聯的記錄的外鍵列值為null。當且僅當設置了null=True選項時可用。

 

SET_DEFAULT

刪除被參照表的某條表記錄,設置參照表中,同待刪除記錄存在外鍵關聯的記錄的外鍵列值為默認值。必須為外鍵列設置默認值。

 

SET()

刪除被參照表的某條表記錄,設置參照表中,同待刪除記錄存在外鍵關聯關系的記錄的外鍵列值為傳遞給SET()的參數值,如果傳遞給SET()的參數值是可調用對象,則設置為調用可調用對象獲取的結果。

 

官方例子:

from django.conf import settings

from django.contrib.auth import get_user_model

from django.db import models

def get_sentinel_user():

    return get_user_model().objects.get_or_create(username='deleted')[0]

 

class MyModel(models.Model):

    user = models.ForeignKey(

        settings.AUTH_USER_MODEL,

        on_delete=models.SET(get_sentinel_user),

    )

 

DO_NOTHING

刪除被參照表的某條表記錄,不對參照表中同待刪除記錄存在外鍵關聯的記錄做任何處理。

 

 

 

參考鏈接:

https://docs.djangoproject.com/en/1.11/ref/models/fields/#foreignkey

參考鏈接:

https://docs.djangoproject.com/en/1.11/topics/db/models/#relationships

 

 

聯合主鍵

例子:如下,希望project_id和user_id字段組合唯一

class APIProjectFacorites(models.Model):

    id = models.AutoField(primary_key=True, verbose_name='自增id')

    project_id = models.CharField(blank=True, null=True, max_length=300, verbose_name='項目id')

    user_id = models.CharField(blank=True, null=True, max_length=15, verbose_name='用戶id')

 

    class Meta:

        db_table = 'tb_api_project_facorities'

        unique_together = ("project_id", "user_id")

        verbose_name = 'API項目收藏表'

        verbose_name_plural = verbose_name

 

 

組織models

1、如果manager.py 啟動app,會創建包含一個models.py的文件。如果有許多model,可以按單個文件的方式組織model。新建models包來管理,具體方法如下:

 

然后移除models.py,並創建一個myapp/models目錄,在該目錄下新建__init__.py文件,用於存放models。

 

例:

假設在models目錄下存在models文件,organic.py 和synthetic.py,編輯myapp/models/__init__.py,新增以下內容:

from .organic import Person

from .synthetic import Robot

 

 

 

參考鏈接:

https://docs.djangoproject.com/en/1.11/topics/db/models/

 

https://docs.djangoproject.com/en/1.11/

 

 

 


免責聲明!

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



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