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后台和调试时使用
三、参数说明
常用字段类型
常用字段参数
Meta选项
四、代码示例
示例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()时自动更新。两个参数不能同时使用,且设置后字段在表单中默认不可编辑。
七、关系类型对比
小贴士
设计数据库模型时,建议先绘制实体关系图(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更加内聚。
本文涉及AI创作
内容由AI创作,请仔细甄别