🍉 前言
系列文章目录
🍉 Django 模型
Django 框架中,模型用于实现与数据库的交互,如数据的增删改查等。
在 Django 框架中,模型用于描述数据库表结构,一个模型(Model)对应一个数据表,模型中的字段对应数据表中的一个字段,一个模型对象对应数据表中的一条记录。
🍉 定义模型
所有的 Django 模型必须继承 Model 类,Model 类位于包 django.db.models 中。
🥝 语法
from django.db.models import Model class 模型名(Model): 字段 其他属性或方法 ...
🥝 常用模型字段类型
🥑 AutoField
数据库中的自动增长类型,相当于自动增长的IntegerField类型字段,对应MySQL中的int类型,可以用于ID的自动增长。
通常我们不需要设置该类型的ID字段,因为如果没有指定,django会为表创建自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后django不会再创建自动增长的主键列。
🥑 BooleanField
一个真/假(True/False)的布尔类型字段,对应MySQL中的tinyint类型。
该类型的字段如果没有设置默认值,则该字段的默认值为None。
该类型的字段默认对应CheckboxInput表单部件。
🥑 NullBooleanField
支持Null、True、False三种值。
🥑 CharField
字符类型字段,对应MySQL中的varchar类型。
该类型的字段必须设置字符的最大个数,即必须设置max_length参数。
该类型的字段默认对应TextInput表单部件。
🥑 DateField
日期字段,对应MySQL中的date类型。
该类型的字段默认对应DateInput表单部件。
对于 DateField 字段,有auto_now_add、auto_now两个参数:
1.auto_now_add:
该参数的默认值为False,如果将该参数的值设置为True,则会自动将该字段的值设置为创建时的时间,后期不能再次修改,且无法手动为该字段赋值。
该参数可以用于记录用户注册时间的字段。
2.auto_now:
该参数的默认值为False,如果将该参数的值设置为True,则会自动将该字段的值设置为当前的时间,且无法手动为该字段赋值。
该参数可以用于记录用户登录时间的字段。
注意:auto_now_add、auto_now和default选项是相互排斥的。这些选项的任何组合都会导致错误。如果将 auto_now 或 auto_now_add 设置为 True,将导致该字段设置为 editable=False(设置为不可手动编辑) 和 blank=True(不允许为空)。
🥑 DateTimeField
日期时间类型字段,对应MySQL中的datetime类型。
DateTimeField类型的字段和DateField类型的字段一样,有auto_now_add、auto_now两个参数,且用法相同。
🥑 TimeField
时间类型字段,对应MySQL中的time类型。
TimeField类型的字段和DateField类型的字段一样,有auto_now_add、auto_now两个参数,且用法相同。
🥑 IntegerField
整数类型字段,对应MySQL中的int类型。
该类型的字段的取值范围为 -2147483648 到 2147483647 ,如果取值在该范围内,则在 Django 支持的所有数据库中都是安全的。
🥑 TextField
长文本类型字段,对应MySQL中的longtext类型。
该字段的默认表单部件是一个 Textarea。该类型的字段如果指定了 max_length 属性,则 max_length 属性将会反映在自动生成的表单字段的 Textarea 部件中。
🥑 FloatField
浮点数类型字段,对应MySQL中的double类型。
FloatField 类有时会与 DecimalField 类混淆。它们都表示实数,但它们表示的方式不同。FloatField 内部使用 Python 的 float 类型,而 DecimalField 则使用 Python 的 Decimal 类型。
🥑 FileField
字符类型字段,对应MySQL中的varchar类型。
🥑 ImageField
字符类型字段,对应MySQL中的varchar类型。
🥑 DecimalField
数值型类型字段,对应MySQL中的decimal类型。
该类型字段表示固定精度的十进制。
有两个必要的参数:
1.DecimalField.max_digits:数字中允许的最大位数。注意,这个数字必须大于或等于 decimal_places。
2.DecimalField.decimal_places:与数字一起存储的小数位数。
🥝 常用字段参数
字段参数 | 含义 |
verbose_name | 设置字段在admin后台管理显示的名称,如果没有指定字段名称,Django 会使用模型类中字段的属性名自动创建,并会将属性名中的下划线转换为空格。 |
primary_key | 设置字段为主键 |
editable | 设置该字段是否可以编辑,一般用于admin后台 |
max_length | 设置字段的最大长度 |
blank | 默认值为False,如果设置为True,则该字段允许为空值,该空值在数据库中表现为空字符串 |
null | 默认值为False,如果设置为True,则该字段允许为空值,该空值在数据库中表现为null |
default | 设置字段的默认值 |
choice | 设置字段的可选值,django 模型 choices 详解 |
db_column | 设置模型对应数据表中的列名称,如果没有进行设置,则将属性名作为列名称 |
db_index | 是否在数据库中为字段建立索引,如果是 True,将为该字段创建数据库索引 |
unique | 是否在数据库中为字段建立唯一索引,如果设置为 True,这个字段的取值必须在整个表中保持值唯一 |
error_messages | 自定义错误信息 |
validators | 自定义错误验证 |
null是数据库范畴的概念,blank是表单验证范畴的概念
🥝 代码示例–定义模型类
导入 models 模块:
from django.db import models
🥑 UserBaseInfo
class UserBaseInfo(models.Model): """ 用户基本信息表 """ id = models.AutoField(verbose_name='编号', primary_key=True) username = models.CharField(verbose_name='用户名', max_length=30) password = models.CharField(verbose_name='密码', max_length=20) status = models.CharField(verbose_name='状态', max_length=1) # 指定在数据库表中字段的名称为createDate,且自动将该字段的值设置为创建时的时间后期不能再次修改,不能手动为该字段赋值 createdate = models.DateTimeField(verbose_name='创建时间', db_column='createDate', auto_now_add=True)
🥑 UserExtraInfo
class UserExtraInfo(models.Model): """ 用户扩展信息表 """ id = models.AutoField(verbose_name='编号', primary_key=True) username = models.CharField(verbose_name='用户名', max_length=30) password = models.CharField(verbose_name='密码', max_length=20) sex = models.CharField(verbose_name='性别', max_length=1, default='male') salary = models.DecimalField(verbose_name='工资', max_digits=8, decimal_places=2) # 最大位数8位,其中小数2位 birthday = models.DateField(verbose_name='出生日期') age = models.IntegerField(verbose_name='年龄', default=0) email = models.CharField(verbose_name='邮箱', max_length=30, blank=True) # 允许为空,为空时数据库中存储的数据为空字符串 status = models.CharField(verbose_name='状态', max_length=1) createdate = models.DateTimeField(verbose_name='创建时间', db_column='createDate', auto_now_add=True)
🥑 DepartInfo
class DepartInfo(models.Model): """ 部门信息表 """ id = models.AutoField(verbose_name='编号', primary_key=True) departname = models.CharField(verbose_name='部门名称', max_length=20) createdate = models.DateTimeField(verbose_name='创建时间', db_column='createDate', auto_now_add=True)
🥑 SkillInfo
class SkillInfo(models.Model): """ 员工技能表 """ id = models.AutoField(verbose_name='编号', primary_key=True) skillname = models.CharField(verbose_name='技能名称', db_column='skillName', max_length=20) createdate = models.DateTimeField(verbose_name='创建时间', db_column='createDate', auto_now_add=True)
🥝 __str__()
方法
__str__()
方法用于设置输出模型对象时的返回值,默认的返回值为模型对象,可以通过__str__()
方法设置打印模型对象的返回值。
注意:__str__()
方法只允许返回字符类型的字段,如果要返回其他类型的字段,需要使用str()函数将字段的值转换为字符类型。
🥑 代码示例
class UserBaseInfo(models.Model): """ 用户基本信息表 """ ...... def __str__(self): # 由于`__str__()`方法只允许返回字符类型的字段,所以对于整数类型的id字段需要使用str()函数将字段的值转换为字符类型 return str(self.id) + ': ' + '用户名-' + self.username + '\t用户状态-' + self.status class UserExtraInfo(models.Model): """ 用户扩展信息表 """ ...... def __str__(self): return str(self.id) + ': ' + '用户名-' + self.username + '\t用户状态-' + self.status class DepartInfo(models.Model): """ 部门信息表 """ ...... def __str__(self): return str(self.id) + ': ' + '部门名称-' + self.departname class SkillInfo(models.Model): """ 员工技能表 """ ...... def __str__(self): return str(self.id) + ': ' + '技能名称-' + self.departname
测试:
from subapp01.models import UserBaseInfo, UserExtraInfo, DepartInfo, SkillInfo # 导入模型类型 from django.http import HttpResponse # 导入返回响应的类 # Create your views here. def fun(request): users = UserBaseInfo.objects.all() # 获取userbaseinfo表中的所有记录 for user in users: # 循环遍历打印userbaseinfo表中的所有用户信息记录对象 print(user) # str(self.id) + ': ' + '用户名-' + self.username + '\t用户状态-' + self.status return HttpResponse(users) # 向客户端返回响应
🥝 Meta 类
Django 模型中的 Meta 类是一个内部类,用于定义一些 Django 模型的行为特性。
Meta 类的常用参数:
参数 | 含义 |
abstract | 如果将该参数的值设置为True,则该模型类为抽象类 |
db_table | 设置该模型对象的数据表的名称,如果没有设置该参数,则默认的数据表名称为“应用名+下划线+模型类名” |
ordering | 模型对象返回的记录结果集按照哪个字段进行排序。按照字段升序排列:ordering=[“字段名”];按照字段降序排列:ordering=[“-字段名”];按照多个字段进行排序:ordering=[“字段名1”, “字段名2”, …] |
verbose_name | 设置模型类在后台管理中显示的名称 |
index_together | 设置数据库中表的联合索引 |
unique_together | 设置数据库中表的联合唯一索引 |
🥑 代码示例
class UserBaseInfo(models.Model): """ 用户基本信息表 """ ...... def __str__(self): ...... class Meta: db_table = 'user_base_info' # 在数据库中该模型对应的表的名称 verbose_name = '用户基本信息表' # 模型类在后台管理中显示的名称
🍉 模型的关系
数据库中的表存在一对一、一对多、多对多的关联关系,Django中的模型对应数据库中的表,所以,Django中的模型也存在一对一、一对多、多对多的关联关系。
🥝 一对一
建立Django模型之间一对一的关联关系,在模型中使用models模块下OneToOneField()方法来构建模型的一对一关联关系。
使用OneToOneField()方法来构建模型间的一对一关联关系,相当于在模型中创建了一个引用另一个模型指定字段的外键。
哪个数据表需要外键,就把OneToOneField()方法放到该数据表对应的模型中。
models模块下OneToOneField()方法的参数:
参数 | 含义 |
to | 要进行关联的模型名称 |
to_field | 要进行关联的模型中的字段名称 |
on_delete | 指定在删除关联模型(被引用)中的数据时,对本模型中的数据如何进行处理 |
on_delete参数的配置选项:
配置选项 | 含义 |
CASCADE | 在删除关联模型(被引用)中的数据时,如果外键所在的模型(引用)一并删除有关联的数据,即级联删除 |
PROTECT | 在删除关联模型(被引用)中的数据时,采用保护机制抛出错误,不删除外键所在模型(引用)的相关数据,即阻止删除操作 |
SET_NULL | 在删除关联模型(被引用)中的数据时,对于外键所在的模型(引用)如果外键字段null=True,则将外键所在模型(引用)的外键字段的相关数据设置为null |
SET_DEFAULT | 在删除关联模型(被引用)中的数据时,对于外键所在的模型(引用)如果外键字段有设置默认值,则将外键所在模型(引用)的外键字段的相关数据设置为默认值 |
SET | 在删除关联模型(被引用)中的数据时,将外键所在模型(引用)的外键字段的相关数据设置为指定的值 |
DO_NOTHING | 在删除关联模型(被引用)中的数据时,对于外键所在的模型(引用)不做任何操作 |
🥑 代码示例
用户基本信息表UserBaseInfo和用户扩展信息表UserExtraInfo之间的关系为一对一的关系,由于在用户基本信息表中需要建立外键关联用户扩展信息表中的数据记录,所以在用户基本信息表对应的模型中使用OneToOneField()方法建立外键关联用户扩展信息表的数据记录。
class UserExtraInfo(models.Model): """ 用户扩展信息表 """ ...... class UserBaseInfo(models.Model): """ 用户基本信息表 """ ...... # 设置外键,关联用户扩展信息表,且用户扩展信息表数据删除时进行级联操作删除基本信息表的信息,该字段允许为空 # 自动关联用户扩展信息表的主键 user = models.OneToOneField(to=UserExtraInfo, on_delete=models.CASCADE, null=True) def __str__(self): ...... class Meta: ......
🥝 一对多
建立Django模型之间一对多的关联关系,在模型中使用models模块下ForeignKey()方法来构建模型间的一对多关联关系。
通常把ForeignKey()方法放到“多”的数据表对应的模型中,即在“多”对应的模型中建立引用“一”对应的模型中字段数据的外键。
ForeignKey()方法的参数:
参数 | 含义 |
to | 要进行关联的模型名称 |
to_field | 要进行关联的模型中的字段名称 |
on_delete | 指定在删除关联模型(被引用)中的数据时,对本模型中的数据如何进行处理,在ForeignKey()方法中的on_delete的配置选项与OneToOneField()方法中的on_delete的配置选项一致 |
related_name | 默认值为None,指定在反向操作时访问“多”对应模型使用的字段名,即通过“一”对应的模型查询“多”对应的模型中的相关数据时使用的字段名(外键定义在“多”对应的模型中),如果没有指定,则反向操作时使用的字段名为“表名_set” |
related_query_name | 默认值为None,在反向操作时访问“多”对应模型中某个字段使用的名字,如果没有指定,则反向操作时使用的名字为“表名_字段名”,只能指定前缀,即“表名” |
db_constraint | 是否在数据库中创建外键约束,设置为True,在数据库中创建外键约束 |
🥑 代码示例
用户扩展信息表UserExtraInfo和部门信息表DepartInfo之间的关系为多对一的关系,由于在用户扩展信息表中需要建立外键关联部门信息表,所以在用户扩展信息表对应的模型中使用ForeignKey()方法建立外键关联部门信息表。
class DepartInfo(models.Model): """ 部门信息表 """ ...... class UserExtraInfo(models.Model): """ 用户扩展信息表 """ ...... depart = models.ForeignKey( to=DepartInfo, # 关联的模型为部门信息模型DepartInfo null=True, # 该字段允许为空 on_delete=models.SET_NULL, # 当部门信息表的记录删除时将该表的相关数据的相关字段设置为null related_name='user_extra_info', # 当进行反向操作时,使用user_extra_info代表该模型 db_constraint=True # 在数据库中建立外键约束 ) def __str__(self): ......
🥝 多对多
建立Django模型之间多对多的关联关系,在模型中使用models模块下ManyToManyField()方法来构建模型间的多对多关联关系。
对于使用ManyToManyField()方法建立模型之间的多对多关系,该方法放在哪个模型并没有什么区别,因为通过ManyToManyField()方法建立模型之间的多对多关系,会在数据库中生成一个关联两个模型对应的数据表的第三张表。
ManyToManyField()方法的参数:
参数 | 含义 |
to | 要进行关联的模型名称 |
db_constraint | 是否在数据库中创建外键约束,设置为True,在数据库中创建外键约束 |
db_table | 默认值为None,指定关联两个模型对应表的第三张表的表名,如果不指定则第三张表表名默认为“模型名称1_模型名称2” |
🥑 代码示例
用户扩展信息表UserExtraInfo和用户技能表SkillInfo之间的关系为多对多的关系,使用ManyToManyField()方法建立两个模型之间的多对多关联。
class SkillInfo(models.Model): """ 用户技能表 """ ...... class UserExtraInfo(models.Model): """ 用户扩展信息表 """ ...... # 建立该模型与用户技能模型之间的多对多关联关系,在数据库中创建外键约束,用于关联两个模型对应表的第三表的表名为user_skill skill = models.ManyToManyField(to=SkillInfo, db_constraint=True, db_table='user_skill') def __str__(self): ......
🍉 迁移数据在数据库生成表
🥝 生成迁移文件
在迁移数据之前,首先要生成迁移文件。
生成所有子应用迁移文件的命令:
python manage.py makemigrations
在此之前已有进行数据迁移,所以在这迁移的为修改后的内容
🥝 执行迁移
执行迁移,在数据库中创建对应的表,将数据同步到数据库中。
在第一次进行迁移时,数据库中不能存在同名的数据表,否则会迁移失败
执行迁移的命令:
python manage.py migrate
🥝 之前迁移过程截图
生成迁移文件
python manage.py makemigrations
如果报错:
No changes detected
原因:可能子应用没有进行注册
数据迁移同步到数据库中
python manage.py migrate