Django model 層之Models與Mysql資料庫小結 by:授客 QQ:1033553122 測試環境: Python版本:python-3.4.0.amd64 下載地址:https://www.python.org/downloads/release/python-340/ Win7 ...
Django model 層之Models與Mysql資料庫小結
by:授客 QQ:1033553122
測試環境:
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, PASSWORD,HOST, 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 protected]', 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/