django Model模型层详解

作为django框架的「大脑中枢接口」,Model层是连接业务逻辑Python代码relational-database数据的桥梁。今天我们就用清晰的实操路线,把django ORM和Model的核心知识点啃下来~


课程目标

  1. 理解django ORM的定位、价值
  2. 掌握Model的基础定义语法、字段类型
  3. 熟练操作数据库迁移(从创建表到维护表结构)
  4. 学会用QuerySet完成CRUD和常用查询

django ORM简介

ORM(Object-Relational Mapping,对象关系映射)不是django独有的,但却是django生态中「最具开发效率」的模块之一:

  • 它把数据库表映射成Python类(我们写的Model)
  • 表中的一条记录映射成类的一个实例
  • SQL的增删改查、过滤、排序等封装成Python的方法/属性调用

为什么我们要用它?

优势点具体说明
跨数据库兼容一套代码几乎可以无缝切换SQLite/MySQL/PostgreSQL/Oracle等主流relational-database
防SQL注入所有用户输入的查询条件都会被django自动转义,无需手动处理安全隐患
Python原生用Python的类、属性、方法、链式调用这些熟悉的语法写逻辑,不用记复杂的SQL
可维护性高业务逻辑和数据结构定义都在Python文件里,没有零散的SQL,方便版本控制和修改

Model的定义

Model类必须写在django应用的models.py文件里,且必须继承自django.db.models.Model

第一个完整的Model

我们先写一个文章管理Model,覆盖基础字段、通用字段选项、__str__方法和Meta类:

from django.db import models
from django.utils import timezone  # 推荐用django内置的时区处理工具


class Article(models.Model):
    # 字段定义(通用字段选项放在参数里)
    title = models.CharField(
        max_length=200,  # CharField必须加的必填项
        null=False,       # 数据库层面不允许为NULL
        blank=False,      # 表单验证层面不允许为空(和null配合使用更严谨)
        help_text="文章标题(最多200字)"  # 后台/admin/表单会显示的提示文本
    )
    content = models.TextField(help_text="文章正文内容")
    pub_date = models.DateTimeField(
        "发布时间",  # 可选的第一参数,指定字段在后台/admin的显示名
        default=timezone.now  # 默认值设为当前时间
    )
    author = models.CharField(max_length=100)
    views = models.IntegerField(default=0, help_text="文章阅读量")

    # __str__方法:定义实例在Python终端、后台/admin的显示文本
    def __str__(self):
        return f"《{self.title}》 - {self.author}"

    # Meta类:定义Model的「元数据」(表名、排序、后台显示名等)
    class Meta:
        ordering = ["-pub_date"]  # 默认按发布时间倒序排列(减号表示倒序)
        verbose_name = "文章"       # 后台/admin显示的单数名
        verbose_name_plural = "文章"  # 后台/admin显示的复数名(中文一般单数复数一致)

高频常用字段类型

django内置了几十种字段类型,覆盖了绝大多数开发场景,这里列最常用的:

字段类型适用场景注意事项
CharField短文本(标题、姓名、邮箱前缀)必须指定max_length
TextField长文本(文章正文、评论、说明)不用指定长度
IntegerField整数(年龄、数量、ID)也可以用PositiveIntegerField限制正整数
DecimalField金额、精度要求高的小数必须指定max_digits(总位数)和decimal_places(小数位数)
DateTimeField日期时间(发布时间、创建时间)搭配auto_now_add(创建时自动设置)或auto_now(修改时自动设置)使用很方便
BooleanField布尔值(是否发布、是否置顶)默认值可以设TrueFalse
ForeignKey多对一关系(一篇文章对应一个作者)必须指定to(关联的Model)和on_delete(删除关联数据的策略)
ManyToManyField多对多关系(一篇文章对应多个标签)不用指定on_delete,删除策略由django自动处理

数据库迁移

Model类只是Python层面的「数据结构描述」,要让它真正变成数据库里的表,必须执行迁移(Migration)操作。

迁移的两步核心流程

1. 生成迁移文件(makemigrations

这一步会检测models.py的变化,并生成一个Python脚本文件(存放在对应应用的migrations文件夹里),这个脚本是「可逆的」,不用担心改坏表结构。

# 生成所有应用的迁移文件
python manage.py makemigrations

# 生成指定应用的迁移文件(推荐,更精准)
python manage.py makemigrations blog  # 假设你的应用叫blog

2. 执行迁移(migrate

这一步会读取迁移文件,并把它翻译成SQL语句,真正在数据库里创建/修改/删除表。

# 执行所有未应用的迁移
python manage.py migrate

# 执行指定应用的迁移
python manage.py migrate blog

常用的迁移辅助命令

查看迁移状态

# 查看所有应用的迁移文件状态([X]表示已应用,[ ]表示未应用)
python manage.py showmigrations

# 查看指定应用的迁移状态
python manage.py showmigrations blog

回滚迁移

# 回滚到指定的迁移版本(比如blog应用的0001_initial)
python manage.py migrate blog 0001_initial

# 回滚到迁移前的状态(删除该应用的所有表)
python manage.py migrate blog zero

QuerySet基础操作

Model类的objects属性是django自动生成的管理器(Manager),所有的数据库操作都要通过它来调用,返回的结果是一个QuerySet(可以理解为「延迟执行的查询集」,只有在真正用到数据的时候才会去数据库查,性能很高)。

创建记录(Create)

方法1:save()

先实例化Model类,再手动调用save()方法,适合需要修改实例属性后再保存的场景。

from blog.models import Article
from django.utils import timezone

# 1. 实例化
article = Article(
    title="django Model入门教程",
    content="今天我们来学习django的Model层...",
    author="张三",
    pub_date=timezone.now()
)
# 2. 手动修改属性(可选)
article.views = 10
# 3. 保存到数据库
article.save()

方法2:create()

直接通过管理器的create()方法创建并保存,适合不需要额外修改属性的场景,代码更简洁。

Article.objects.create(
    title="django ORM的优势",
    content="django ORM有跨数据库兼容、防SQL注入等优势...",
    author="李四"
)

查询记录(Retrieve)

获取所有记录

# 返回所有Article的QuerySet
all_articles = Article.objects.all()

获取单个记录

注意:get()方法必须返回且只能返回一条记录,如果没有或有多个,会抛出异常。

# 用主键id查询(最常用)
article = Article.objects.get(id=1)

# 用其他唯一字段查询(比如unique=True的slug)
# article = Article.objects.get(slug="django-model-intro")

获取第一条/最后一条记录

# 按默认排序(Meta里的ordering)取第一条
first_article = Article.objects.first()

# 按默认排序取最后一条
last_article = Article.objects.last()

过滤查询(filter()

filter()方法返回符合条件的多条记录的QuerySet,支持链式调用。

# 查询作者是张三的文章
zhang_articles = Article.objects.filter(author="张三")

# 查询2024年发布的文章(双下划线__表示字段查询操作)
2024_articles = Article.objects.filter(pub_date__year=2024)

# 链式调用:查询2024年发布、作者是张三的文章
zhang_2024_articles = Article.objects.filter(author="张三").filter(pub_date__year=2024)

更新记录(Update)

更新单个记录

save()创建记录的流程类似,先查询到实例,修改属性后再save()

article = Article.objects.get(id=1)
# 修改属性
article.title = "django Model入门教程(升级版)"
article.views += 1  # 阅读量加1
# 保存
article.save()

批量更新

直接通过filter()+update()方法,不需要先查询实例,效率更高,适合修改大量符合条件的记录。

# 把所有作者是张三的文章的阅读量加100
Article.objects.filter(author="张三").update(views=models.F("views") + 100)
# 注意:批量更新不能用普通的Python变量,要用models.F()来引用数据库里的字段值

删除记录(Delete)

删除单个记录

先查询到实例,再调用delete()方法。

article = Article.objects.get(id=1)
article.delete()

批量删除

直接通过filter()+delete()方法,不需要先查询实例,效率更高。

# 删除所有2022年之前发布的文章
Article.objects.filter(pub_date__lt="2022-01-01").delete()

课程总结

今天我们从ORM的定位入手,学习了:

  1. 如何用Python类定义一个完整的django Model
  2. 高频常用的字段类型和通用字段选项
  3. 数据库迁移的两步核心流程和辅助命令
  4. QuerySet的基础CRUD操作(创建、查询、更新、删除)

这些都是django开发的核心基础,熟练掌握它们后,我们就可以进一步学习Model的关联关系、高级查询、性能优化等内容啦~