Django 数据模型
🗃️ Django ORM 的力量
Django的ORM(对象关系映射)让你可以使用Python类来定义数据模型,而无需编写SQL。模型是Django应用的核心。
什么是Django模型?
Django模型是Python类,它们:
- 映射到数据库表
- 定义表字段和数据类型
- 包含业务逻辑和方法
- 提供数据库查询的Pythonic接口
创建第一个模型
1
打开 models.py
在应用目录中编辑models.py文件:
from django.db import models
2
定义模型类
创建一个简单的博客文章模型:
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
is_published = models.BooleanField(default=False)
def __str__(self):
return self.title
模型代码解释:
• title - 字符字段,最大长度200
• content - 文本字段,无长度限制
• created_at - 创建时自动设置时间
• updated_at - 每次保存时自动更新
• is_published - 布尔值,默认未发布
• __str__ - 定义对象的显示名称
常用字段类型
📝
CharField
短文本字段,必须指定max_length
title = models.CharField(max_length=100)
📄
TextField
长文本字段,适合文章内容等
content = models.TextField()
🔢
IntegerField
整数字段
age = models.IntegerField()
💰
DecimalField
十进制数字,适合金额等
price = models.DecimalField(max_digits=10, decimal_places=2)
✅
BooleanField
布尔值字段
is_active = models.BooleanField(default=True)
📅
DateTimeField
日期和时间字段
created = models.DateTimeField(auto_now_add=True)
📧
EmailField
邮箱字段,自动验证格式
email = models.EmailField()
🔗
URLField
URL字段,自动验证格式
website = models.URLField()
字段常用参数
| 参数 |
说明 |
示例 |
default |
字段默认值 |
default=True |
null |
是否允许数据库NULL值 |
null=True |
blank |
是否允许表单验证为空 |
blank=True |
choices |
可选值列表 |
choices=STATUS_CHOICES |
unique |
字段值是否唯一 |
unique=True |
verbose_name |
可读的字段名称 |
verbose_name="标题" |
help_text |
帮助文本 |
help_text="请输入文章标题" |
模型关系
一个模型实例关联另一个模型的一个实例
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField()
使用场景: 用户扩展信息、配置信息等
一个模型实例关联多个另一个模型的实例
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
content = models.TextField()
使用场景: 博客文章和评论、订单和商品等
一个模型实例关联多个另一个模型的实例,反之亦然
class Article(models.Model):
tags = models.ManyToManyField(Tag)
title = models.CharField(max_length=200)
使用场景: 文章和标签、学生和课程等
on_delete 参数详解
| 选项 |
说明 |
使用场景 |
CASCADE |
级联删除,关联对象一并删除 |
评论随文章删除 |
PROTECT |
保护模式,阻止删除操作 |
有订单的用户不能删除 |
SET_NULL |
设置为NULL,需要null=True |
文章作者离职,文章保留 |
SET_DEFAULT |
设置为默认值 |
设置默认分类 |
SET() |
设置为指定值 |
自定义设置逻辑 |
DO_NOTHING |
什么也不做(不推荐) |
数据库级别约束 |
完整模型示例
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
name = models.CharField(max_length=100, unique=True)
description = models.TextField(blank=True)
class Meta:
verbose_name = "分类"
verbose_name_plural = "分类"
ordering = ['name']
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):
STATUS_CHOICES = [
('draft', '草稿'),
('published', '已发布'),
('archived', '已归档'),
]
title = models.CharField(max_length=200, verbose_name="标题")
content = models.TextField(verbose_name="内容")
author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="作者")
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True)
tags = models.ManyToManyField(Tag, blank=True)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='draft')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
published_at = models.DateTimeField(null=True, blank=True)
class Meta:
verbose_name = "文章"
verbose_name_plural = "文章"
ordering = ['-created_at']
indexes = [
models.Index(fields=['status', 'created_at']),
]
def __str__(self):
return self.title
def publish(self):
self.status = 'published'
self.published_at = timezone.now()
self.save()
def is_recent(self):
return self.created_at >= timezone.now() - timedelta(days=7)
示例代码分析:
• Category模型 - 文章分类,包含名称和描述
• Tag模型 - 文章标签,多对多关系
• Post模型 - 核心文章模型,包含:
• 状态选择字段(choices)
• Meta类 - 模型元数据配置
• 数据库索引优化
• 自定义方法 - 业务逻辑封装
• publish() - 发布文章
• is_recent() - 检查是否最近创建
模型元数据 (Meta)
| 选项 |
说明 |
示例 |
db_table |
自定义数据库表名 |
db_table = 'blog_posts' |
ordering |
默认排序规则 |
ordering = ['-created_at'] |
verbose_name |
单数可读名称 |
verbose_name = "文章" |
verbose_name_plural |
复数可读名称 |
verbose_name_plural = "文章" |
unique_together |
联合唯一约束 |
unique_together = ['user', 'post'] |
indexes |
数据库索引 |
indexes = [models.Index(fields=['status'])] |
constraints |
数据库约束 |
constraints = [models.CheckConstraint(...)] |
default_related_name |
默认反向关系名称 |
default_related_name = 'posts' |
数据库迁移
迁移工作流程
1
创建迁移文件
检测模型变更并生成迁移文件:
$ python manage.py makemigrations
↓
2
查看迁移SQL
可选:查看将要执行的SQL语句:
$ python manage.py sqlmigrate myapp 0001
↓
3
应用迁移
执行迁移,创建或修改数据库表:
$ python manage.py migrate
迁移文件示例
0001_initial.py
初始迁移,创建所有模型表
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = []
operations = [
migrations.CreateModel(
name='Post',
fields=[...],
),
]
ORM 查询示例
🔍 常用查询操作
Django ORM 提供了丰富的查询API,让你可以使用Python语法操作数据库。
posts = Post.objects.all()
post = Post.objects.get(id=1)
published_posts = Post.objects.filter(status='published')
drafts = Post.objects.exclude(status='published')
user_posts = Post.objects.filter(author__username='john')
recent_posts = Post.objects.order_by('-created_at')[:5]
from django.db.models import Count
post_count = Post.objects.aggregate(Count('id'))
查询性能优化
posts = Post.objects.all()
for post in posts:
print(post.author.username)
posts = Post.objects.select_related('author').all()
for post in posts:
print(post.author.username)
posts = Post.objects.prefetch_related('tags').all()
模型设计最佳实践
- 使用有意义的字段名 - 避免使用缩写
- 设置适当的verbose_name - 便于admin显示
- 定义__str__方法 - 便于调试和显示
- 使用choices代替魔法数字 - 提高可读性
- 添加数据库索引 - 优化查询性能
- 使用select_related/prefetch_related - 避免N+1查询
- 编写模型方法 - 封装业务逻辑
- 避免过宽的表 - 字段过多影响性能
- 不要忽略on_delete - 必须指定删除行为
- 避免过度规范化 - 平衡性能和可维护性
- 不要硬编码ID - 使用get_or_create等
- 避免在循环中保存 - 使用bulk_create
- 不要忘记迁移 - 模型变更后及时迁移
- 避免长文本索引 - 影响性能
🔒 数据验证规则
在模型层面确保数据完整性:
- 使用
unique=True确保字段唯一性
- 设置适当的
max_length限制
- 使用
choices限制可选值
- 通过模型
clean()方法实现复杂验证
- 使用数据库约束(unique_together, constraints)
交互式模型构建器
🎯 尝试构建你的模型
选择字段类型和参数,实时生成模型代码:
生成的模型代码:
from django.db import models
class MyModel(models.Model):
title = models.CharField(max_length=200)
def __str__(self):
return self.title
下一步学习
👁️
Admin 后台
学习如何注册模型到Django管理后台
学习Admin
🔍
视图和模板
掌握如何在视图中使用模型数据
学习视图
🧪
模型测试
学习如何为模型编写测试用例
学习测试