Django模型定义与字段类型详解
本文深入解析Django模型的核心机制,涵盖模型类的继承、表名配置及主键生成规则。详细列举BigAutoField、CharField等常用字段类型及其关键参数如null与blank的区别,并说明Django 3.2后DEFAULT_AUTO_FIELD的配置变化。此外,通过示例演示外键ForeignKey的关联方式、级联删除策略及choices选项的实际应用,帮助开发者规范数据库设计。
Django模型
在Django框架中,模型的定义通常位于models.py文件内。作为MVT架构中的M(Model),它同时也对应于传统MVC架构中的模型层,负责处理数据逻辑与数据库交互。
构建Django模型时,必须让自定义类继承自django.db.models.Model基类。以下是一个基础示例:
from django.db import models
# Create your models here.
class BookInfo(models.Model): # 一个模型类就会对应生成数据库中的一张表
"""书籍模型"""
name = models.CharField(max_length=128, verbose_name='名称') # 类的属性就是数据表中的字段。
pub_date = models.DateField(verbose_name='发布日期',null=True)
readcount = models.IntegerField(default=0, verbose_name='阅读量')
commentcount = models.IntegerField(default=0, verbose_name='评论量')
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
class Meta: # class Meta是固定写法
db_table = 'bookinfo' # 指明数据库表名
verbose_name = '图书' # 在admin站点中显示的名称
注意
1. 若未在模型中显式指定表名,Django将自动使用“小写应用名_小写模型类名”作为数据库表名。通常建议通过Meta类中的db_table属性明确指定表名,以符合命名规范。
2. Django会自动为每张表生成一个自增的主键列。每个模型仅能拥有一个主键。若手动指定某个字段为主键,Django将不再创建默认的id列。默认主键列名为id,也可通过pk属性访问,代表primary key。
3. 字段名称严禁包含双下划线(__),因为这是Django查询语法中用于过滤和关联的特殊符号,混用会导致解析错误。
自Django 3.2版本起,开发者可在settings.py中通过DEFAULT_AUTO_FIELD配置项指定主键的数据类型。默认值为'django.db.models.BigAutoField'。在Django 3.2之前的版本中,默认生成的主键类型为AutoField。
以下是Django中常用的字段类型及其详细说明:
字段类型
| 类型 | 说明 |
|---|---|
| BigAutoField | 自动增长的BigIntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性 |
| BooleanField | 布尔字段,值为True或False |
| NullBooleanField | 支持Null、True、False三种值 |
| CharField | 字符串,参数max_length表示最大字符个数 |
| TextField | 大文本字段,一般超过4000个字符时使用 |
| IntegerField | 整数 |
| DecimalField | 十进制浮点数, 参数max_digits表示总位数, 参数decimal_places表示小数位数 |
| FloatField | 浮点数 |
| DateField | 日期, 参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add和auto_now是相互排斥的,组合将会发生错误 |
| TimeField | 时间,参数同DateField |
| DateTimeField | 日期时间,参数同DateField |
| FileField | 上传文件字段 |
| ImageField | 继承于FileField,对上传的内容进行校验,确保是有效的图片 |
在定义字段时,除了指定类型,还需配置相应的参数以控制行为。常见参数如下:
字段类型的参数
| 参数 | 说明 |
|---|---|
| null | 如果为True,表示允许为空,默认值是False |
| blank | 如果为True,则该字段允许为空白,默认值是False |
| db_column | 字段的名称,如果未指定,则使用属性的名称 |
| db_index | 若值为True, 则在表中会为此字段创建索引,默认值是False |
| default | 为字段指定默认值 |
| primary_key | 若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用 |
| unique | 如果为True, 这个字段在表中必须有唯一值,默认值是False |
| choices | 该参数是从一系列的二元组中提供选项 |
注意
1. CharField字段必须指定max_length参数,用于限制字符串的最大长度,这既是数据库层面的约束,也是Django表单验证的依据。
2. 可通过verbose_name参数为字段指定显示名称,主要用于Django Admin管理界面及本地化展示。例如,将name字段的verbose_name设置为“书籍名称”,则在Admin后台中该字段标签将显示为“书籍名称”。
3. null与blank参数的作用层面不同:null=True作用于数据库层,允许该字段在数据库中存储NULL值;blank=True作用于表单验证层(HTML表单),表示提交表单时该字段可以为空。通常建议同时设置null=True和blank=True以保持一致性。
外键
外键关系通常在业务逻辑层面实现,而非直接依赖数据库层面的约束(尽管数据库设计范式如第三范式强调外键约束)。Django通过ORM机制简化了这一过程。以下示例展示了PeopleInfo模型如何通过外键与之前的BookInfo模型关联:
class PeopleInfo(models.Model):
"""人员模型"""
GENDER_CHOICES = (
(0, 'male'),
(1, 'female')
)
name = models.CharField(max_length=20, verbose_name='名称')
gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')
description = models.CharField(max_length=200, null=True, verbose_name='描述信息')
book = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书') # 外键
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
class Meta:
db_table = 'peopleinfo'
verbose_name = '人物信息'
下面重点来说一下choices这个参数和models.ForeignKey。
choices参数就是从我们定义的二元组(GENDER_CHOICES)中获取值。二元组的第一个值会储存在数据库中,而第二个值将只会用于在表单中显示。对于一个模型实例,要获取该字段二元组中相对应的第二个值,使用 get_FOO_display() 方法。例如:获取上面的性别信息,可以使用get_gender_display()方法。
外键:通过使用models.ForeignKey来设置外键,ForeignKey的第一个参数是要关联的模型类名,第二个参数是on_delete。它的常用值可以如下:
CASCADE级联,删除主表数据时连通一起删除外键表中数据
PROTECT保护,通过抛出ProtectedError异常,来阻止删除主表中被外键应用的数据
SET_NULL设置为NULL,仅在该字段null=True允许为null时可用
SET_DEFAULT设置为默认值,仅在该字段设置了默认值时可用
SET()设置为特定值或者调用特定方法
DO_NOTHING不做任何操作,如果数据库前置指明级联性,此选项会抛出IntegrityError异常
注意:在标准SQL数据库中设置外键需明确指定关联的字段名,但在Django中无需显式指定,因为Django默认使用关联表的id字段作为关联依据。具体效果如下图所示:

观察生成的数据库表结构,PeopleInfo表中的外键字段名为book_id,这符合Django的默认命名规则。
总结
本文至此结束,希望能为读者提供有价值的参考。欢迎持续关注本站,获取更多关于Django开发的技术内容!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









