上一篇的内容中,我们已经基本上完成了一个简单的项目,现在我们要学习Django中MVT中M的部分 -- 模型
模型准确的描述了一条数据,Django使用ORM(对象关系映射)技术来将一个python类映射为数据库的一张表,而类中的每个类属性映射为表中的一个字段。
编写模型类
- 要想编写模型类,需要知道以下几点:
- 模型类需要继承自models.Model
- 类属性映射为字段,字段的类型使用models.字段类型指定
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
- Django提供的一般的模型类字段可以满足大部分的需求,但是如果你越到了更加复杂或者是更加特定的业务场景,你也可以自定义模型类的字段来映射你更加特别的数据库数据。
- Django会根据模型类名和应用名来自动扩展为数据库的表名(如果不使用db_table指定表名的话),表名使用的是应用名小写_模型类名来作为表的名字
- 模型类中不需要定义id列,Django会自动生成并且维护自增id,但是如果你明确指定了其他主键列的话,Django将不会再生成并且维护id列了。
- Meta选项(指定模型类的元数据)
- abstract: 如果设置为True,那么这个模型类将被当作抽象模型基类。
- 这里简单的介绍一下抽象模型基类,简单的来说,抽象模型基类就是在父类中定义需要子类实现的方法,但是自己本身并没有实现,而是会调用该方法,这些方法被预期在子类中进行实现,这也通常是一种设计模式的体现。
- app_label: 当你的模型类定义在别的地方的时候(也就是不在子应用的models文件中),需要使用该参数指定该模型类所属的app。
- db_table:指定数据库的表明,不指定的话,默认使用应用名_模型类名小写做表名。
- indexes: 指定为哪些字段创建索引
- ordering: 指定排序的字段以及排序的方式,如果想使用降序排序,在字段名前加-,例如 ordering=['-pub_date']表名按照发布日期降序排序。
- verboase_name:指定一个可读性好的名称。
- abstract: 如果设置为True,那么这个模型类将被当作抽象模型基类。
indexes = [
models.Index(fields=['last_name', 'first_name']), fields指定需要创建索引的字段
models.Index(fields=['first_name'], name='first_name_idx'), name参数指定索引的名字
]
如果你想自己指定数据库表的主键,在你想要设置为主键的字段上设置选项参数primary_key=True,Django将不会在自动创建id。
每个模型类都需要设置主键。
字段类型
这里介绍几个常用的字段类型:
BooleanField
(布尔字段)CharField
(字符串字段) 对于大量的文本,请使用TextFieldDateField
(日期字段)格式为年- 是python中datetime.date的实例表示
- autonow参数指定了每次保存数据的时候,将时间设置为当前的时间。对于update_time等时间戳字段是常见的。该字段的值只会在调用save()的时候自动的进行更新。
- auto_now_add当创建对象的时候,自动的将值设置为当前的时间。对于create_time等创建时间的时间戳是很参见的选项。
DateTimeField
(日期字段)格式为年-月 参见DateField的使用。是datetime.datetime的实例。IntegerField
(整型字段)DecimalField
(小数字段) 十进制数字字段,是Decimal的实例,有两个必须的参数- max_digits: 指定允许的最大位数,必须大于小数的位数
- decimal_places: 指定小数的位数,
TextField
(文本字段)URLField
(URL字段)
字段类型用来指定对应数据库存储的数据类型,需要和数据库表相对应。
尽量不要在数据库中存储json形式的数据,这一般是最佳实践。
关联关系字段
关联关系字段也是属于一种特殊的字段类型,我们主要使用的关联关系字段主要有以下三种:
ForeignKey
(外键)通常用于一对多关系ManyToManyField
通常用于多对多关系- OneToOneField:用于一对一关系。
1. ForeignKey字段需要两个必要参数,被关联的模型类和on_delete选项,也接收其他可选参数,具体的内容参见Django3.0文档中关于field的介绍。
2. 如果需要创建一个自关联关系的话,使用models.ForeignKey('self', on_delete=models.CASCADE)
on_delete指定了当某一条数据被删除的时候,与其想关联的数据的处理方式,主要有以下几个选项:
1. CASCADE:级联删除,当某条数据被删除的时候,与其相关的对象也将被删除,为的是数据库的一致性。
2. SET_NULL:将相关对象的值设置为空,注意,需要在该字段允许为空的时候使用,否则会报错。
3. SET_DEFAULT:将相关对象的值设置为默认值。
4. PROTECT:通过抛出异常来阻止相关对象被删除。
5. DO_NOTHING:什么都不做。
6. SET():将需要设置的值传递给SET,也可以是一个可调用的对象。
3. 如果需要在未定义的模型上创建关联关系的话,可以使用模型的名称而不是模型本身。
4. 要关联定义在另一个程序中定义的模型,可以显式指定带有应用程序标签名的模型
(应用程序名,模型类名),注意这里使用的是字符串的形式。
5. ManyToManyField: 用于多对多关系,可以定义在任何一方,但是不能同时在两端都定义,会造成循环引用问题。
6. 定义多对多关系的时候,普通的ManyToManyField一般来讲适用于简单的多对多关系,如果你需要添加额外的数据在多对多关系中的话,这时候,就需要使用一个中间模型类(相当于一张中间表)来表示多对多关系了,中间表使用ManyToManyField的through参数来指定。
其次,如果你的多对多模型类中存在对另一个模型类的多个外键的时候,这时候,Django并不知道要使用哪一个外键来连接,所以需要我们使用through filelds参数来指定,through_fields使用两元素元祖的形式指定。
members = models.ManyToManyField(
Person,
through='Membership',
through_fields=('group', 'person'),
)
7. OneToOneField的使用形式可以参考ForeignKey的使用形式。
字段选项 ---通用参数
知道了字段有哪些类型之后,我们还需要知道,字段类型有怎样的选项,字段的选项是用来检验字段,提供约束的。
1.null
如果设置为True
,当该字段为空时,Django 会将数据库中该字段设置为NULL
。默认为False
。(注意,这是一个和数据库相关的概念,表示的是数据库中存储的值是NULL)
要避免CharField等字段类型的选项参数中出现null=True,因为这样的话,数据库中没有值就会存在两种情况,一种是空字符串,一种是NULL。
2.blank
如果设置为True
,该字段允许为空。默认为False
。 (注意:blank是一个和表单验证相关的概念,和null并不一样,blank=True表示的是允许该参数为空值,可以不传)。
3. choice,是一个列表嵌套二元元祖的形式,每一个二元组的第一个参数是保存在数据库中的值,第二个参数是展示在页面上的值。
要想获取choice字段的显示值(第二个参数的值),使用get_字段名_display()方法调用。
4. default,指定该字段的默认值。可以是一个值,也可以是一个可调用对象,如果是一个可调用 对象的话,每次实例化模型类的时候都会调用。
5. primary_key,指定该字段为表的主键,默认情况下,Django自动设置并且维护id主键列。
如果你自己指定主键,Django将不再生成id主键列。
6. unique:设置该字段是否唯一,如果设置为True,字段的值必须在数据库中保持唯一。
注意一种特殊的情况,当某个字段被设置为unique=True并且blank=True的时候,一定需要设置null=True,否则会因为唯一值的验证导致报错。
字段选项 ---可选参数
1. verbose_name:指定字段在admin站点显示的名称。ForeignKey
,ManyToManyField
andOneToOneField
接收的第一个参数为模型的类名,后面可以添加一个verbose_name
参数
2. db_index: 设置为True的时候,会为该字段创建索引,可以使用元数据的方式指定。
3. max_ length:一般用于CharField,用来指定最大长度。
4. db_column:指定数据库列的名称,默认使用字段的名称。
5. editable:设置为Flase的时候,将在admin展示和模型类的验证中跳过该字段。默认是True。
6. validator:指定该字段的验证函数列表,用于验证使用。