Django 模型(长文解析)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

在 Django 开发中,"Django 模型" 是连接业务逻辑与数据库的核心桥梁。它通过 Python 类的形式,将数据库表结构抽象为易于操作的对象,使得开发者无需直接编写 SQL 语句即可高效管理数据。无论是构建个人博客、电商平台,还是复杂的管理系统,掌握 Django 模型的设计与使用都是不可或缺的基础技能。本文将从零开始,通过循序渐进的方式,结合实际案例,深入解析 Django 模型的构建逻辑、核心概念及进阶技巧,帮助开发者快速掌握这一关键工具。


核心概念解析

1. 模型的定义与作用

Django 模型(Django Model)是 Django 框架中用于描述数据库表结构的 Python 类。每个模型对应数据库中的一张表,其字段(Field)对应表的列,实例对应表的行。通过模型,开发者可以:

  • 定义数据结构:指定字段类型(如字符串、整数、日期等)和约束条件(如唯一性、非空等)。
  • 自动创建数据库表:通过 makemigrationsmigrate 命令,模型会自动生成对应的数据库迁移文件。
  • 执行数据库操作:模型的 Manager 和 QuerySet 提供了丰富的 API,用于增删改查数据。

比喻:如果把数据库比作一座图书馆,模型就是设计这座图书馆的蓝图。它规定了每本书(数据行)的书架位置(表)、书的分类(字段类型)和存放规则(约束条件)。

2. 模型的创建步骤

以一个简单的书籍管理应用为例,创建一个 Book 模型:

from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=50)
    publication_date = models.DateField()
    price = models.DecimalField(max_digits=5, decimal_places=2)
    is_available = models.BooleanField(default=True)
  • 继承 models.Model:每个模型必须继承自 Django 的 Model 类。
  • 字段定义:每个字段(如 titleauthor)对应数据库表的一列,字段类型决定了存储的数据格式(如 CharField 对应 VARCHAR)。
  • 默认值与约束default=Trueis_available 字段设定了默认值,max_length 限制了字符串长度。

关键字段类型详解

Django 模型提供了丰富的字段类型,覆盖了常见的数据存储需求。以下列举高频使用的字段及使用场景:

字段类型描述典型用途
CharField存储短文本,需指定 max_length 参数。用户名、标题、地址
TextField存储长文本,无长度限制。文章内容、评论
IntegerField存储整数。年份、库存数量
DecimalField存储精确小数,需指定 max_digitsdecimal_places价格、金额
DateTimeField存储日期和时间,默认使用当前时间。创建时间、更新时间
BooleanField存储布尔值(True/False)。是否可用、是否删除标志
ForeignKey表示与其他模型的一对多关系。用户与订单(一个用户多个订单)
ManyToManyField表示模型之间的多对多关系。书籍与作者(一本书多个作者)

示例

class Author(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(unique=True)

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

此处 ForeignKey 将书籍与作者关联,on_delete=models.CASCADE 表示删除作者时,关联的书籍也会被级联删除。


数据关系模型设计

Django 模型支持 一对一(OneToOne)一对多(OneToMany)多对多(ManyToMany) 三种关系类型,适用于不同业务场景。

1. 一对多关系(OneToMany)

场景:例如,一个出版社(Publisher)可以出版多本书籍(Book)。

class Publisher(models.Model):
    name = models.CharField(max_length=255)

class Book(models.Model):
    title = models.CharField(max_length=100)
    publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)

此时,Django 会为 Book 表添加一个 publisher_id 外键字段。通过 publisher.book_set 可以获取该出版社的所有书籍。

2. 多对多关系(ManyToMany)

场景:例如,一本书可能有多个标签(Tag),一个标签也可能关联多本书。

class Tag(models.Model):
    name = models.CharField(max_length=50)

class Book(models.Model):
    tags = models.ManyToManyField(Tag)

Django 会自动生成一张中间表(如 book_tag),存储 book_idtag_id 的对应关系。

3. 一对一关系(OneToOne)

场景:例如,用户(User)与个人资料(Profile)的关联。

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField()

OneToOneField 会直接创建一张新表,并包含被关联模型的主键作为外键。


查询集(QuerySet)与数据操作

Django 的 QuerySet 提供了强大的数据库查询接口,支持链式调用和复杂条件筛选。

1. 基本查询操作

  • 获取所有数据

    all_books = Book.objects.all()  # 返回 QuerySet 对象
    
  • 条件筛选

    # 过滤价格高于 50 元的书籍
    expensive_books = Book.objects.filter(price__gt=50.00)
    
    # 排除已下架的书籍
    available_books = Book.objects.exclude(is_available=False)
    

    操作符说明
    __gt(大于)、__lt(小于)、__contains(包含)、__startswith(以...开头)等。

  • 排序与分页

    # 按价格降序排列
    sorted_books = Book.objects.order_by('-price')
    
    # 分页(每页 10 条)
    page_books = Book.objects.all()[start:end]
    

2. 创建与更新数据

  • 创建新记录
    new_book = Book.objects.create(
        title="Python进阶指南",
        author="张三",
        price=69.90,
        is_available=True
    )
    
  • 更新现有记录
    book = Book.objects.get(id=1)
    book.price = 79.90
    book.save()  # 提交更改到数据库
    

3. 关联对象的查询

通过模型关系字段,可以轻松访问关联对象:

author = Book.objects.get(id=1).author

author_books = Author.objects.get(name="张三").book_set.all()

进阶技巧与最佳实践

1. 自定义模型管理器(Manager)

默认的 objects 管理器可通过继承 models.Manager 自定义查询逻辑:

class PublishedBookManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(is_available=True)

class Book(models.Model):
    objects = models.Manager()          # 默认管理器
    published = PublishedBookManager()  # 自定义管理器
    
available_books = Book.published.all()

2. 元数据(Meta)配置

通过 class Meta 可定义模型的元数据,例如排序规则、表名等:

class Book(models.Model):
    class Meta:
        ordering = ['-publication_date']  # 按出版日期降序排列
        verbose_name = "书籍"             # 在管理界面显示的名称
        db_table = 'tb_books'             # 自定义数据库表名

3. 信号(Signals)与钩子函数

使用 Django 信号或模型的 save()delete() 方法钩子,实现在数据操作时执行额外逻辑:

from django.db.models.signals import pre_save
from django.dispatch import receiver

@receiver(pre_save, sender=Book)
def update_price(sender, instance, **kwargs):
    if instance.price < 0:
        instance.price = 0.00

实战案例:博客系统模型设计

1. 需求分析

假设要构建一个包含文章(Post)、评论(Comment)和标签(Tag)的博客系统,需满足以下条件:

  • 每篇文章可关联多个标签。
  • 每条评论需关联一篇文章和用户。
  • 文章需记录创建时间和更新时间。

2. 模型实现

from django.contrib.auth.models import User
from django.utils import timezone

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()
    created_at = models.DateTimeField(default=timezone.now)
    updated_at = models.DateTimeField(auto_now=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    tags = models.ManyToManyField(Tag)
    
    class Meta:
        ordering = ['-created_at']
        
class Comment(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    text = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

3. 数据操作示例

post = Post.objects.create(
    title="Django模型深度解析",
    content="本文详细讲解了Django模型的创建与使用...",
    author=request.user
)
post.tags.add(Tag.objects.get(name="Django"))

comments = Comment.objects.filter(post=post)

tag = Tag.objects.get(name="Python")
count = tag.post_set.count()

总结与展望

通过本文的讲解,读者应已掌握 Django 模型的核心概念、字段类型、数据关系设计以及查询操作。Django 模型不仅简化了数据库交互的复杂性,还通过强大的 ORM 层实现了代码与 SQL 的解耦,极大提升了开发效率。

对于中级开发者,建议进一步探索以下方向:

  • 数据库优化:通过索引、分表分库提升查询性能。
  • 复杂查询:使用 annotate()aggregate() 实现聚合计算。
  • 序列化与 API:结合 Django REST Framework 将模型数据转换为 JSON 格式。

掌握 Django 模型是构建数据驱动应用的第一步,后续可通过实际项目不断深化理解。希望本文能为读者提供清晰的入门路径,并激发对 Django 生态的持续学习兴趣。

最新发布