pin_drop当前位置:知识文库 ❯ 图文

Django Model模型 - ORM字段类型与数据库关系详解

一、概述

Model是Django ORM的核心,每个Model类对应数据库中的一张表,类的属性对应表的字段。Django通过Model提供数据库抽象层,开发者无需编写SQL即可完成数据库操作。Model支持字段类型定义、约束、关系、索引等,是Django数据层的基础。

Django ORM(Object-Relational Mapping)是Django框架中最强大的功能之一。它将Python类映射到数据库表,将类属性映射到表字段,将类实例映射到表记录。通过ORM,开发者可以使用Python代码进行数据库操作,而不需要编写原生SQL语句,大幅提高了开发效率和代码可读性。


二、语法

定义Django Model的基本语法如下:

代码示例

from django.db import models

class MyModel(models.Model):
    field_name = models.FieldType(options)

    class Meta:
        db_table = 'table_name'
        ordering = ['-id']

    def __str__(self):
        return self.field_name
  • models.Model:所有Model类必须继承的基类

  • field_name:字段名称,对应数据库列名

  • FieldType:字段类型,如CharField、IntegerField等

  • Meta类:定义模型的元数据,如表名、排序等

  • __str__:定义对象的字符串表示,在Admin后台和调试时使用


三、参数说明

常用字段类型

字段类型 说明 数据库类型
CharField 字符串 VARCHAR
TextField 长文本 TEXT
IntegerField 整数 INT
FloatField 浮点数 FLOAT
BooleanField 布尔值 BOOL
DateField 日期 DATE
DateTimeField 日期时间 DATETIME
DecimalField 精确小数 DECIMAL
EmailField 邮箱 VARCHAR
URLField URL VARCHAR
FileField 文件 VARCHAR(path)
ImageField 图片 VARCHAR(path)
ForeignKey 外键 INT(FK)
ManyToManyField 多对多 中间表
OneToOneField 一对一 INT(UK)

常用字段参数

参数 类型 说明
null bool 是否允许数据库NULL
blank bool 表单是否允许空值
default any 默认值
unique bool 是否唯一
max_length int 最大长度(CharField)
verbose_name str 人类可读名称
choices list 可选值列表
related_name str 反向关系名称

Meta选项

选项 说明
db_table 自定义表名
ordering 默认排序
unique_together 联合唯一
index_together 联合索引
verbose_name 模型可读名称

四、代码示例

示例1:定义基本Model

代码示例

from django.db import models

class Article(models.Model):
    STATUS_CHOICES = [
        ('draft', '草稿'),
        ('published', '已发布'),
    ]

    title = models.CharField('标题', max_length=200)
    content = models.TextField('内容')
    status = models.CharField('状态', max_length=10, choices=STATUS_CHOICES, default='draft')
    views = models.IntegerField('浏览量', default=0)
    created_at = models.DateTimeField('创建时间', auto_now_add=True)
    updated_at = models.DateTimeField('更新时间', auto_now=True)

    class Meta:
        db_table = 'articles'
        ordering = ['-created_at']
        verbose_name = '文章'
        verbose_name_plural = '文章'

    def __str__(self):
        return self.title
  • STATUS_CHOICES:定义状态选项,用于下拉选择

  • auto_now_add=True:首次创建时自动设置时间

  • auto_now=True:每次保存时自动更新时间

  • ordering:设置查询时的默认排序规则,负号表示降序

示例2:定义关系Model

代码示例

from django.db import models

class Category(models.Model):
    name = models.CharField('分类名', max_length=100, unique=True)

    class Meta:
        verbose_name = '分类'
        verbose_name_plural = '分类'

    def __str__(self):
        return self.name

class Tag(models.Model):
    name = models.CharField('标签名', max_length=50, unique=True)

    def __str__(self):
        return self.name

class Post(models.Model):
    title = models.CharField('标题', max_length=200)
    content = models.TextField('内容')
    # 外键:多对一
    category = models.ForeignKey(
        Category, on_delete=models.CASCADE,
        related_name='posts', verbose_name='分类'
    )
    # 多对多
    tags = models.ManyToManyField(Tag, blank=True, verbose_name='标签')

    created_at = models.DateTimeField('创建时间', auto_now_add=True)

    def __str__(self):
        return self.title

这个示例展示了三种模型关系的使用方式:

  • ForeignKey(多对一):多篇文章属于一个分类,通过on_delete=models.CASCADE设置级联删除

  • ManyToManyField(多对多):文章可以有多个标签,标签也可以属于多篇文章,Django自动创建中间表

  • related_name:设置反向查询名称,可以通过category.posts.all()获取分类下的所有文章

示例3:Model字段约束和验证

代码示例

from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator

class Product(models.Model):
    name = models.CharField('商品名', max_length=200, db_index=True)
    price = models.DecimalField(
        '价格', max_digits=10, decimal_places=2,
        validators=[MinValueValidator(0)]
    )
    stock = models.IntegerField('库存', default=0, validators=[MinValueValidator(0)])
    discount = models.FloatField(
        '折扣', default=1.0,
        validators=[MinValueValidator(0), MaxValueValidator(1)]
    )
    is_active = models.BooleanField('是否上架', default=True)
    description = models.TextField('描述', blank=True, default='')
    sku = models.CharField('SKU', max_length=50, unique=True)

    class Meta:
        db_table = 'products'
        ordering = ['name']
        unique_together = ['name', 'sku']

    def __str__(self):
        return f"{self.name} - ¥{self.price}"
  • db_index=True:为字段创建数据库索引,加速查询

  • validators:字段验证器,确保数据符合业务规则

  • max_digits和decimal_places:DecimalField必须指定的精度参数

  • unique_together:联合唯一约束,确保name和sku组合唯一


五、实际应用场景

  • 博客系统:定义文章、分类、标签、评论等模型,通过外键和ManyToManyField建立关联关系

  • 电商系统:定义商品、订单、购物车、用户等模型,使用DecimalField处理价格,使用DateTimeField记录时间

  • 社交系统:定义用户、帖子、评论、关注等模型,使用ManyToManyField处理关注关系,使用ForeignKey处理评论归属


六、注意事项

注意:null是数据库级别约束,blank是表单验证级别约束,两者独立。TextField和CharField通常设置null=False, blank=True,因为数据库中空字符串和NULL语义不同。

注意:CharField必须指定max_length,这是数据库VARCHAR类型的限制。TextField用于存储长文本,不需要指定max_length,但不同数据库对TEXT类型有大小限制。

注意:ForeignKey的on_delete参数必填,CASCADE表示级联删除(删除父记录时自动删除子记录)。其他常用选项包括PROTECT(阻止删除)、SET_NULL(设为NULL)、SET_DEFAULT(设为默认值)。

注意:auto_now_add在创建记录时自动设置,之后不再改变;auto_now在每次调用save()时自动更新。两个参数不能同时使用,且设置后字段在表单中默认不可编辑。


七、关系类型对比

关系 字段 说明 示例
多对一 ForeignKey 多个记录属于一个 文章-分类
多对多 ManyToManyField 互相属于多个 文章-标签
一对一 OneToOneField 一一对应 用户-资料

小贴士

设计数据库模型时,建议先绘制实体关系图(ER图),明确各实体之间的关联关系。对于复杂的多对多关系,如果中间表需要存储额外字段(如通过时间、状态等),可以使用through参数自定义中间表模型,获得更大的灵活性。


八、小结

  • Model类对应数据库表,属性对应字段

  • 字段类型丰富,支持字符串、数字、日期、文件等

  • ForeignKey/ManyToManyField/OneToOneField定义模型关系

  • Meta类配置表名、排序、索引等元数据


九、练习题

练习1

定义一个Book模型,包含书名、作者、价格、出版日期、ISBN等字段,设置合适的约束

练习2

定义Student和Course两个模型,一个学生可以选多门课,一门课可以被多个学生选(多对多关系)

常见问题

null和blank有什么区别?

null是数据库层面的约束,控制是否允许字段存储NULL值。blank是表单验证层面的约束,控制表单是否允许该字段为空。对于字符串字段(CharField、TextField),Django建议设置null=False, blank=True,用空字符串代替NULL,因为数据库中NULL和空字符串的语义不同,且字符串字段使用空字符串可以避免额外的NULL检查。

如何自定义Model的表名?

在Model的Meta类中设置db_table属性即可。例如:class Meta: db_table = 'my_custom_table'。如果不设置,Django会自动使用"应用名_模型名"的小写格式作为表名,如blog_article。自定义表名在与现有数据库集成时非常有用。

ForeignKey的on_delete有哪些选项?

CASCADE:级联删除,删除父记录时自动删除所有关联的子记录。PROTECT:阻止删除,如果存在关联的子记录则抛出ProtectedError。SET_NULL:将外键设为NULL(需要null=True)。SET_DEFAULT:将外键设为默认值(需要default参数)。SET():设置为指定值。DO_NOTHING:不做任何操作(可能导致数据库完整性错误)。

如何在Django中执行原生SQL查询?

使用Model.objects.raw()方法可以执行原生SQL:MyModel.objects.raw('SELECT * FROM myapp_mymodel WHERE id > %s', [10])。也可以使用django.db.connection执行任意SQL。但建议优先使用ORM查询,只有在ORM无法表达复杂查询或需要极致性能时才使用原生SQL。

Django Model如何添加自定义方法?

直接在Model类中定义方法即可。例如:def get_full_name(self): return f"{self.first_name} {self.last_name}"。自定义方法可以访问Model的所有字段和其他方法。也可以使用@property装饰器将方法转为属性访问。自定义方法通常用于封装业务逻辑,使Model更加内聚。

标签: Django Model ORM 数据库模型 ForeignKey 字段类型 Meta选项

本文涉及AI创作

内容由AI创作,请仔细甄别

list快速访问

上一篇: Django应用创建 - startapp命令与模块化开发指南 下一篇: Django View视图完整教程:函数视图与类视图详解 - 零基础入门指南

poll相关推荐