Model (模型) 简而言之即数据模型,是一个Django应用的核心。模型不是数据本身(比如数据表里的数据), 而是抽象的描述数据的构成和逻辑关系。
每个Django的模型(model)实际上是个类,继承了models.Model。每个Model应该包括属性(字段),关系(比如单对单,单对多和多对多)和方法。当你定义好Model模型后,Django的接口会自动帮你在数据库生成相应的数据表(table)。
一个标准的Django模型分别由模型字段、META选项和方法三部分组成。我们接下来对各部分进行详细介绍。Django官方编码规范建议按如下方式排列:
models.Model提供的常用模型字段包括基础字段和关系字段。
from django.db import models
class MyModel(models.Model):
my_char_field = models.CharField(max_length=100)
from django.db import models
class MyModel(models.Model):
my_text_field = models.TextField()
from django.db import models
class MyModel(models.Model):
my_date_field = models.DateField()
DateField 用于存储日期,不包括时间
可通过default=xx选项设置默认日期和时间。
对于DateTimeField: default=timezone.now - 先要from django.utils import timezone
如果希望自动记录一次修改日期(modified),可以设置: auto_now=True
如果希望自动记录创建日期(created),可以设置auto_now_add=True
auto_now_add:布尔值,默认为 False。如果设置为 True,则当对象首次被创建时,字段会被设置为当前日期。
auto_now:布尔值,默认为 False。如果设置为 True,则每次对象保存时,字段会被设置为当前日期。
blank:布尔值,默认为 False。如果设置为 True,则该字段允许为空。
null:布尔值,默认为 False。如果设置为 True,则 Django 在数据库中使用 NULL 来存储空值。
default:字段的默认值。这可以是一个日期值,或者一个返回日期值的可调用对象。
editable:布尔值,默认为 True。如果设置为 False,这个字段将不会在 Django 管理界面或者任何 ModelForm 中显示。
help_text:用于在表单字段旁边显示额外的帮助文本。
verbose_name:为字段设置一个人类可读的名字。
FileField(upload_to=None, max_length=100) - 文件字段
upload_to = “/some folder/”:上传文件夹路径
max_length = xxxx:文件最大长度
ImageField (upload_to=None, max_length=100,)- 图片字段
OneToOneField(to, on_delete=xxx, options) - 单对单关系
to必需指向其他模型
必需指定on_delete选项(删除选项): i.e, “on_delete =
models.CASCADE” or “on_delete = models.SET_NULL” .
可以设置 “related_name = xxx” 便于反向查询。
ForeignKey(to, on_delete=xxx, options) - 单对多关系
to必需指向其他模型.
必需指定on_delete选项(删除选项): i.e, “on_delete = models.CASCADE” or “on_delete = models.SET_NULL” .
可以设置”default = xxx” or “null = True” ;
如果有必要,可以设置 “limit_choices_to = “,
可以设置 “related_name = xxx” 便于反向查询。
ManyToManyField(to, options) - 多对多关系
对于OneToOneField和ForeignKey, on_delete选项和related_name是两个非常重要的设置,前者决定了了关联外键删除方式,后者决定了模型反向查询的名字。
Django提供了如下几种关联外键删除选项, 可以根据实际需求使用。
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')
在这个例子中,Book 模型有一个指向 Author 模型的 ForeignKey。通过设置 related_name=‘books’,我们可以在 Author 实例上使用 books 属性来获取所有与之相关的 Book 实例。
重要特性
如果没有指定 related_name,Django 会自动创建一个默认的名称,格式为
如果你的模型被用于多个 ForeignKey 或 ManyToManyField,为每个关系指定一个唯一的 related_name 是一个好的实践,这样可以避免命名冲突。
如果你不希望为关系创建反向名称,可以将 related_name 设置为 ‘+’ 或者 None(在 Django 1.9 及以后版本中)。
示例
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='publications')
class Article(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='articles')
在这个例子中,Author 可以通过 publications 属性获取其所有的 Book 实例,通过 articles 属性获取其所有的 Article 实例。
使用 related_name:
author = Author.objects.get(name="Jane Doe")
author_books = author.publications.all() # 获取所有与Jane Doe相关的书籍
author_articles = author.articles.all() # 获取所有与Jane Doe相关的文章
如果不使用 related_name:
author_books = Book.objects.filter(author=author) # 使用默认的related_name
author_articles = Article.objects.filter(author=author) # 使用默认的related_name
在 Django 中,每个模型都有一个内部类叫做 Meta,它用于包含模型的元数据,即关于模型自身的配置信息。这些元数据不会直接转换为数据库字段,但它们会影响模型的行为,尤其是在数据库层面和 Django 管理界面中的表现。
以下是一些常用的 Meta 选项及其用途:
类型:布尔值
默认值:False
用途:如果设置为 True,则模型会被视为抽象基类,不会创建对应的数据库表。
类型:字符串
用途:指定模型所属的应用的名称。通常不需要设置,因为 Django 会自动确定。
类型:字符串
用途:指定模型在数据库中对应的表名。如果不设置,Django 会自动生成表名,格式为
类型:字符串
用途:指定模型使用的数据库表空间。如果数据库支持表空间,这个选项可以用来指定模型表应该使用的表空间。
类型:字符串或字段名
用途:指定一个字段名,通常是日期或时间字段,以便使用 Model.objects.latest() 方法时按照该字段排序获取最新记录。
类型:布尔值
默认值:True
用途:如果设置为 False,Django 不会为该模型创建或删除数据库表。这在模型映射到预先存在的数据库表或是在非数据库数据源上时很有用。
类型:字段名
用途:用于多对多关系,允许对象根据指定的字段进行排序。
类型:字符串或字段列表
用途:指定对象默认的排序方式。例如,[‘name’] 表示按照 name 字段的升序排序。
类型:二元组列表
用途:为模型添加额外的权限。每个元组应该包含两个元素:权限代码和人类可读的权限名称。
类型:布尔值
默认值:False
用途:如果设置为 True,则模型会被视为代理模型。它将继承其父模型的字段,但不会创建新的数据库表。
类型:字段名列表的列表
用途:指定字段组合的唯一性约束。例如,unique_together = [(‘username’, ‘email’)] 表示 username 和 email 的组合必须是唯一的。
类型:字符串
用途:为模型设置一个人类可读的单数名称。
类型:字符串
用途:为模型的复数名称设置一个人类可读的名称。
以下是一个包含 Meta 类的模型示例:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
class Meta:
ordering = ['last_name']
verbose_name_plural = "people"
在 Django 中,模型不仅仅是数据库表的简单映射;它们也是具有行为的 Python 对象。你可以为模型添加自定义的方法来执行各种操作,比如计算字段值、处理相关对象,或者执行任何其他需要的业务逻辑。
以下是一些常见类型的模型方法及其用途:
虽然不是直接在模型上定义的,但管理器方法是模型中经常使用的方法。它们允许你对查询集进行自定义操作。
from django.db import models
class BookManager(models.Manager):
def title_count(self, keyword):
return self.filter(title__icontains=keyword).count()
class Book(models.Model):
title = models.CharField(max_length=100)
objects = BookManager()
# 使用自定义管理器方法
book_count = Book.objects.title_count('django')
这些方法通常用于处理单个模型实例。
class Author(models.Model):
name = models.CharField(max_length=100)
books = models.ManyToManyField(Book)
# book_count 方法返回与特定作者相关的书籍数量。
def book_count(self):
return self.books.count()
类方法与实例方法不同,因为它们不需要特定的实例来调用。它们可以用来返回查询集或者执行与特定实例无关的操作。
class Book(models.Model):
title = models.CharField(max_length=100)
published_date = models.DateField()
#recent_books 类方法返回最近30天内发布的书籍。
@classmethod
def recent_books(cls):
return cls.objects.filter(published_date__gte=datetime.now() - timedelta(days=30))
静态方法不依赖于类或实例的状态。它们用于执行一些不访问任何属性或方法的操作。
class Book(models.Model):
title = models.CharField(max_length=100)
#is_valid_title 静态方法检查给定的标题是否有效。
@staticmethod
def is_valid_title(title):
return len(title) > 0
Django 提供了 save 和 delete 方法的钩子,你可以在这些方法中添加自定义逻辑。
class Book(models.Model):
title = models.CharField(max_length=100)
def save(self, *args, **kwargs):
do_something_before_save()
super(Book, self).save(*args, **kwargs)
do_something_after_save()
def delete(self, *args, **kwargs):
do_something_before_delete()
super(Book, self).delete(*args, **kwargs)
do_something_after_delete()
以下是一个综合了上述方法的模型示例:
from django.db import models
from datetime import datetime, timedelta
class Author(models.Model):
name = models.CharField(max_length=100)
def get_books(self):
return self.book_set.all()
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
published_date = models.DateField()
def was_published_recently(self):
return self.published_date >= datetime.now() - timedelta(days=30)
@classmethod
def get_recent_books(cls):
return cls.objects.filter(published_date__gte=datetime.now() - timedelta(days=30))
def save(self, *args, **kwargs):
if not self.title:
raise ValueError("Book must have a title.")
super(Book, self).save(*args, **kwargs)