這一篇主要是介紹django的模型如何創(chuàng)建, 模型的一些參數(shù), 以及數(shù)據(jù)如何遷移
創(chuàng)建會員模塊
首先我們先創(chuàng)建一個(gè)會員模塊
> cd cms
> python manager.py account
這樣就在根目錄下創(chuàng)建了一個(gè)account文件夾
創(chuàng)建一個(gè)會員模型
關(guān)于數(shù)據(jù)庫的表模型代碼需要寫在models.py文件中
account/models.py中的文件代碼
最終生成的數(shù)據(jù)表的名稱為模塊名_類名
模型中基本分為三塊
- 聲明的字段信息
- 模型的元類, 包含模型的一些配置信息
- 模型的其他方法
模型的字段
模型不僅會影響到數(shù)據(jù)庫表的創(chuàng)建, 而且會影響到后臺表單的展示
我們只介紹最常用的幾種模型字段和選項(xiàng)說明
CharField字段
對應(yīng)的是數(shù)據(jù)庫的varchar字段, 保存字符串
對應(yīng)的表單是input類型
max_length
可以指定字符串的長度, 對應(yīng)的生成的sql代碼就是varchar(64)
DateField字段
對應(yīng)數(shù)據(jù)庫的date字段, 保存年-月-日的信息
對應(yīng)表單中的日期選擇控件
auto_now_add
是指定在數(shù)據(jù)新增時(shí), 自動寫入時(shí)間
auto_now
是無論新增還是更新數(shù)據(jù), 此字段都會更新為當(dāng)前時(shí)間
auto_now_add和auto_now不可以同時(shí)設(shè)置, 否則會提示你
account.Account.update_time: (fields.E160) The options auto_now, auto_now_add, and default are mutually exclusive. Only one of these options may be present.
DateTimeField字段
同DateField字段, 只不過是包含日期+時(shí)間
EmailField
對應(yīng)表單的input, 但是會添加郵件格式校驗(yàn)
django里是郵件字段, 其實(shí)數(shù)據(jù)庫是varchar字段, 最終繼承的是CharField字段, 但是可以輔助驗(yàn)證郵件的格式, 所以它也有max_length
參數(shù)
IntegerField
數(shù)字字段, 對應(yīng)數(shù)據(jù)庫的int(11)類型
max_length
指定最大長度
min_length
指定最小長度
choice
指定字段的選項(xiàng), 格式是((值, 值說明),), 這個(gè)參數(shù)會影響到后臺表單的展示描睦、新增和編輯
SmallIntegerField
存儲范圍比較小, 其他同IntegerField
TextField
文本類型字段, 對應(yīng)數(shù)據(jù)庫的text()
字段的公共參數(shù)
這些參數(shù)基本在所有字段中都可以設(shè)置, 所以單獨(dú)拿出來介紹一下
null
如果是True, 則可以null值, 默認(rèn)是False, 但是在TextField字段中, 這個(gè)應(yīng)該一直是False, 設(shè)置為True, 數(shù)據(jù)庫會報(bào)錯(cuò)
blank
如果是True, 則允許插入空值, 默認(rèn)是False, 這個(gè)插入的是空, 對應(yīng)字符串是'', 而不是null值
choice
字段的選項(xiàng)值, 設(shè)置這個(gè)參數(shù)后, 后臺表單就會變成下拉的格式
db_name
字段名, 如果指定這個(gè), 如果不指定, 采用的是模型類屬性的名稱小寫, 設(shè)置了以后, 則使用這個(gè)名稱
db_index
設(shè)置為True, 則會在這個(gè)字段上創(chuàng)建索引
default
設(shè)置字段的默認(rèn)值, 不僅支持普通的數(shù)據(jù)類型, 也支持函數(shù)
def contact_default():
return {"email": "to1@example.com"}
contact_info = JSONField("ContactInfo", default=contact_default)
editable
如果是False, 則不會展示在后臺或者任何其他的ModelForm中, 也會跳過模型驗(yàn)證, 默認(rèn)是True
error_messages
設(shè)置驗(yàn)證失敗時(shí)的錯(cuò)誤信息
account = account = models.CharField(max_length=64, blank=True, verbose_name='用戶名', error_messages={
'max_length': '最大長度不可超過64個(gè)字符'
})
help_text
指定在表單頁面的幫助說明問題
primary_key
默認(rèn)是False, 如果沒有指定字段的這個(gè)參數(shù), 則django會自動添加一個(gè)id字段作為主鍵宿接。
primary_key=True則必然null=False 并且unique=True
unique
如果是True, 則這個(gè)字段必須是唯一的
verbose_name
指定后臺中列表頁, 新增編輯頁面顯示的表單字段名稱
模型元類Meta參數(shù)
django中的元類用來設(shè)置一些指定的操作, 以及后臺的一些設(shè)置
class Account(models.Model):
class Meta:
ordering = ['-id']
verbose_name = '會員'
verbose_name_plural = '會員管理'
class Meta就是一個(gè)元類
app_label
指定此模型所屬的模塊名, 如果更改后, 會影響到表的名稱
base_manager_name
指定模型的基本管理者類名稱(就按照管理者來翻譯吧)
先簡單說一下, 我們在使用django查詢的時(shí)候, 都會執(zhí)行django.objects.
那么為什么要這么麻煩的加一個(gè)objects呢谜喊?
其實(shí)objects的作用就是返回了一個(gè)manager類, 而Model其實(shí)只是模型結(jié)構(gòu)的聲明, Manager類才是真正操作數(shù)據(jù)庫的類
db_table
指定數(shù)據(jù)庫表名
default_manager_name
默認(rèn)管理者的名稱, 和base_manager_name類似, 稍后專門會有一篇文章解釋
get_latest_by
排序用的, 只能設(shè)置DateField, DateTimeField, IntegerField. 這個(gè)會作用于Manager的latest()和earliest()方法
# Latest by ascending order_date.
get_latest_by = "order_date"
# Latest by priority descending, order_date ascending.
get_latest_by = ['-priority', 'order_date']
解釋一下, django中-priority代表倒序, priority代表正序
order
類似get_latest_by, 執(zhí)行查詢時(shí), 會影響到排序方式order_by這個(gè)方法
indexes
設(shè)置表的索引
from django.db import models
class Customer(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
class Meta:
indexes = [
models.Index(fields=['last_name', 'first_name']),
models.Index(fields=['first_name'], name='first_name_idx'),
]
fields 指定索引列, name是索引名
unique_together
指定唯一字段
unique_together = ("driver", "restaurant")
在寫入數(shù)據(jù)時(shí), driverhe restaurant必須是唯一的
verbose_name
指定一個(gè)表的顯示名稱, 影響后臺面包屑導(dǎo)航的顯示名稱
verbose_name_plural
影響后臺列表頁的顯示名稱
以上就把關(guān)于模型常用的參數(shù), 屬性都介紹了, 對照demo的代碼大家可以理解一下
注冊模塊
執(zhí)行數(shù)據(jù)遷移之前, 先要將模塊注冊到項(xiàng)目中, 因?yàn)閐jango的模塊設(shè)計(jì)是可插拔的, 減少耦合性
# cms/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.staticfiles',
'account' # 將模塊名寫入list中就完成了注冊
]
如果不執(zhí)行注冊, 那么項(xiàng)目就不會加載這個(gè)模塊, 也無法執(zhí)行數(shù)據(jù)遷移、模塊訪問, 包括后臺的操作了
同步模型到數(shù)據(jù)庫(數(shù)據(jù)遷移)
創(chuàng)建遷移文件
> cd cms
> python manager.py makemigrations
會提示
Migrations for 'account':
account/migrations/0001_initial.py
- Create model Account
打開account/migrations/0001_initial.py
文件
可以看到我們聲明的Model已經(jīng)轉(zhuǎn)換為了遷移文件, 到這一步其實(shí)還沒有將模型同步到數(shù)據(jù)庫
查看遷移狀態(tài)以及遷移執(zhí)行的sql
python manager.py showmigrations account
account
[ ] 0001_initial
說明0001_initial還未遷移, 如果遷移完成則會變成[x]0001_initial
接下來我們查看一下執(zhí)行遷移會出發(fā)的sql
python manage.py sqlmigrate account 0001_initial
BEGIN;
--
-- Create model Account
--
CREATE TABLE `account_account` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `account` varchar(200) NOT NULL UNIQUE, `password` varchar(32) NOT NULL, `email` varchar(32) NOT NULL, `phone` varchar(11) NOT NULL, `status` integer NOT NULL, `create_time` datetime(6) NOT NULL, `update_time` datetime(6) NOT NULL);
COMMIT;
不同的數(shù)據(jù)庫返回的sql可能是不同的
執(zhí)行遷移
python manager.py migrate
返回
Operations to perform:
Apply all migrations: account, admin, article, auth, contenttypes, sessions
Running migrations:
Applying account.0001_initial... OK
則說明遷移成功, 打開mysql管理工具就可以看到我們創(chuàng)建的account_account
這個(gè)表了