引言
在之前的 Django模型设计 中简单的介绍了如何定义模型类,在这篇中将做一个汇总。让大家更加了解Django模型类。
环境
环境名称 | 版本 |
---|---|
Python | 3.9 |
Django | 3.1.2 |
MySql-Server | 5.7.32 |
PyMySQL | 0.10.1 |
模型类的特性
Django
模型类会根据属性的类型确定以下信息:
- 当前选择的数据库支持字段的类型
- 渲染管理表单时使用的默认html控件
- 在管理站点最低限度的验证
Django
会为表创建自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后 Django
不会再创建自动增长的主键列。
默认创建的主键列属性为 id
,可以使用 pk
代替,pk
全拼为 primary key
。
注意:pk是主键的别名,若主键名为id2,那么pk是id2的别名。
例如:当编写 Django
查询时,可以使用 id or pk
作为查询参数。
Object.objects.get(id=1)
Object.objects.get(pk=1)
pk
代表主键(primary key
),pk
更加独立于实际的主键字段,即您不必关心主键字段是否被称为 id
或object_id
或任何。如果具有不同主键字段的模型,它还可以提高您的一致性。
模型类的字段属性及选项
模型类属性命名限制
- 不能是python的保留关键字。
- 不允许使用连续的下划线,这是由
Django
的查询方式决定的,在第4节会详细讲解查询。 - 定义属性时需要指定字段类型,通过字段类型的参数指定选项,语法如下:
属性 = models.字段类型(选项)
模型类的字段类型
使用时需要引入django.db.models
包
from django.db import models
字段类型如下:
AutoField
自动增长的 IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性。
BooleanField
布尔字段,值为 True
或 False
。
NullBooleanField
支持Null、True、False三种值。
CharField
CharField(max_length=字符长度)
:字符串。参数 max_length
必须设置,表示最大字符个数。
TextField
大文本字段,一般超过 4000
个字符时使用。
IntegerField
IntegerField
:整数类型字段
DecimalField
DecimalField(max_digits=None, decimal_places=None)
:十进制浮点数。
- 参数
max_digits
必须设置,表示总位数。 - 参数
decimal_places
必须设置, 表示小数位数。
FloatField
FloatField
:浮点数类型字段。
DateField
DateField([auto_now=False, auto_now_add=False])
:日期。
- 参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为false。
- 参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false。
- 参数auto_now_add和auto_now是相互排斥的,组合将会发生错误。
TimeField
TimeField
:时间,参数同 DateField
。
DateTimeField
DateTimeField
:日期时间,参数同DateField。
FileField
FileField
:上传文件字段
ImageField
ImageField
:继承于FileField
,对上传的内容进行校验,确保是有效的图片。
BinaryField
存储原始二进制数据的字段
EmailField
邮箱字段,字符串类型,会进行邮箱校验
URLField
字符串类型,会进行URL地址校验
FloatField
浮点数类型字段
更多的字段类型请参考 Django 官方文档 https://docs.djangoproject.com/zh-hans/3.1/ref/models/fields/
字段选项
通过选项实现对字段的约束,选项如下:
选项 | 备注 |
---|---|
null | 如果为True,表示允许为空,默认值是False。 |
blank | 如果为True,则该字段允许为空白,默认值是False。 |
db_column | 字段的名称,如果未指定,则使用属性的名称。 |
db_index | 若值为True, 则在表中会为此字段创建索引,默认值是False。 |
default | 默认值。 |
primary_key | 若为True,则该字段会成为模型的主键字段,默认值是False。 |
unique | 如果为True, 这个字段在表中必须有唯一值,默认值是False。 |
verbose_name | 详细名称,就是起一个更可读的名字 |
choices | 对模型字段选择的枚举。 |
editable | bool 类型,在Admin里是否可编辑, |
help_text | 在 Admin 中提示帮助信息 |
upload_to | 指文件上传到哪个位置 |
null
是数据库范畴的概念,**blank
** 是表单验证范畴的。
当修改模型类之后,如果添加的选项不影响表的结构,则不需要重新做迁移,属性的选项中
default
和blank
不影响表结构。
Django 3
之前一般会通过定义一些 常量
和 元组
来定义 choices
,如下所示:
from django.db import models
class Book(models.Model):
UNPUBLISHED = 'UN'
PUBLISHED = 'PB'
STATUS_CHOICES = [
(UNPUBLISHED, 'Unpublished'),
(PUBLISHED, 'Published'),
]
status = models.CharField(
max_length=2,
choices=STATUS_CHOICES,
default=UNPUBLISHED,
)
然后可以按如下方式使用这些常量,例如:
代码语言:javascript复制unpub_books = Book.objects.filter(status=Book.UNPUBLISHED)
然而 Django 3
之后建议使用 Field.choices
枚举类型定义 choices
选项
Django 3
现在提供了一个Choices
类及其两个子类IntegerChoices
和 TextChoices
。这些类扩展了Python的 Enum
类型,并增加了额外的约束和功能,以使其适用于 Field.choices
。
from django.db import models
class Book(models.Model):
class Status(models.TextChoices):
UNPUBLISHED = 'UN', 'Unpublished'
PUBLISHED = 'PB', 'Published'
status = models.CharField(
max_length=2,
choices=Status.choices,
default=Status.UNPUBLISHED,
)
QuerySet
过滤器可以更新为使用以下 Choices
类:
unpublished_books = Book.objects.filter(status=Book.Status.UNPUBLISHED)
模型关系
关系 | 定义 | 备注 |
---|---|---|
一对多 | models.ForignKey() | 外键约束 ,定义在 ‘多类’ 中 |
多对多 | models.ManyToManyField() | 定义在哪一个模型类中都行 |
一对一 | models.OneToOneField() | 定义在哪一个模型类中都行 |
from django.db import models
class BookInfo(models.Model):
"""图书模型类"""
title = models.CharField(verbose_name=u'图书名称', max_length=20)
author = models.CharField(verbose_name=u'图书作者', max_length=20)
pub_date = models.DateField(verbose_name=u'出版日期')
book_type = models.ForeignKey(BookType, on_delete=models.CASCADE, verbose_name=u'图书类型')
元选项
在模型类中定义类 Meta
,用于设置元信息,如使用 db_table
自定义表的名字。
数据表的默认名称为:
代码语言:javascript复制<app_name>_<model_name>
例:
booktest_bookinfo
例如:在 BookInfo
模型类中添加如下内容,代码如下:
from django.db import models
class BookInfo(models.Model):
"""图书模型类"""
title = models.CharField(verbose_name=u'图书名称', max_length=20)
author = models.CharField(verbose_name=u'图书作者', max_length=20)
pub_date = models.DateField(verbose_name=u'出版日期')
book_type = models.ForeignKey(BookType, on_delete=models.CASCADE, verbose_name=u'图书类型')
def __str__(self):
return self.title
class Meta:
db_table = 'BookInfo' # 表名称
verbose_name = u'图书信息' # 表备注
# 表名复数形式,如果不设置末尾会多一个s
verbose_name_plural = verbose_name
ordering = ['id'] # 排序字段
公众号
新建文件夹X
大自然用数百亿年创造出我们现实世界,而程序员用几百年创造出一个完全不同的虚拟世界。我们用键盘敲出一砖一瓦,用大脑构建一切。人们把1000视为权威,我们反其道行之,捍卫1024的地位。我们不是键盘侠,我们只是平凡世界中不凡的缔造者 。